Skip to content

DOCUMENTATION COMPLÈTE - Projet Format IT Nuxt3

Table des Matières

  1. Vue d'ensemble
  2. Architecture et Structure
  3. Technologies Utilisées
  4. Fonctionnalités Principales
  5. Configuration
  6. Scripts NPM
  7. APIs et Routes Serveur
  8. Composables
  9. Composants Vue
  10. Pages
  11. Base de Données Supabase
  12. Authentification et Sécurité
  13. Déploiement
  14. Guide de Démarrage
  15. Maintenance et Évolutions

1. Vue d'ensemble

Présentation du Projet

Format IT est une plateforme web moderne de formation professionnelle spécialisée dans les métiers de la tech. Le projet est développé avec Nuxt 3 (Vue 3 + TypeScript) et propose une interface complète pour :

  • Les visiteurs : découvrir les formations, candidater, contacter l'organisme
  • Les administrateurs : gérer les formations et les options de financement

Informations Techniques

  • Framework : Nuxt 3.4.1
  • Langage : TypeScript, Vue 3
  • Styling : Tailwind CSS 6.14
  • Base de données : Supabase (PostgreSQL)
  • Email : Nodemailer + SMTP Google Workspace
  • Déploiement : Vercel
  • Port développement : 4000

Localisation

/mnt/d/save/projets/PERSO/nuxt/Format IT/format-it-nuxt3

2. Architecture et Structure

Arborescence du Projet

format-it-nuxt3/
├── assets/                      # Ressources statiques CSS
│   └── css/
│       └── main.css             # CSS global avec Tailwind

├── components/                  # Composants Vue réutilisables
│   ├── AdminNav.vue            # Navigation admin
│   ├── AppHeader.vue           # En-tête avec navigation
│   ├── AppFooter.vue           # Pied de page
│   ├── FormationCardSkeleton.vue
│   ├── FormationCardSkeletonHome.vue
│   └── PatternSvg.vue          # Décoration SVG

├── composables/                 # Logique métier réutilisable
│   └── useFormations.ts        # Gestion des formations

├── layouts/                     # Layouts Vue
│   └── default.vue             # Layout par défaut

├── pages/                       # Pages du site (routing automatique)
│   ├── index.vue               # Accueil
│   ├── organisme.vue           # À propos
│   ├── faq.vue                 # Questions fréquentes
│   ├── financement.vue         # Options de financement
│   ├── candidature.vue         # Formulaire candidature
│   ├── nous-contacter.vue      # Formulaire contact
│   └── admin/
│       ├── index.vue           # Connexion admin
│       ├── formations.vue      # Gestion formations (CRUD)
│       └── financements.vue    # Gestion financements

├── plugins/                     # Plugins Nuxt
│   └── router-scroll.client.ts # Scroll automatique

├── public/                      # Assets publics
│   ├── data/                   # Données JSON
│   ├── file/                   # Fichiers PDF
│   ├── fonts/                  # Polices personnalisées
│   ├── icon/                   # Icônes SVG
│   └── img/                    # Images

├── server/                      # Backend API Nitro
│   └── api/
│       ├── formations.get.ts
│       ├── formations.post.ts
│       ├── formations.delete.ts
│       ├── financements.get.ts
│       ├── financements.post.ts
│       ├── send-candidature.post.ts
│       ├── send-contact.post.ts
│       └── upload-image.post.ts

├── utils/                       # Utilitaires
│   └── supabase.ts             # Client Supabase

├── .env                         # Variables d'environnement (PRIVÉ)
├── .env.example                 # Template .env
├── nuxt.config.ts              # Configuration Nuxt
├── tailwind.config.js          # Configuration Tailwind
├── tsconfig.json               # Configuration TypeScript
├── package.json                # Dépendances
├── vercel.json                 # Configuration Vercel
├── supabase-setup.sql          # Script SQL tables
└── DOCUMENTATION.md            # Ce fichier

Principe de Routing

Nuxt 3 utilise le file-based routing :

  • Chaque fichier dans /pages devient automatiquement une route
  • Exemple : pages/organisme.vuehttp://localhost:4000/organisme
  • Les dossiers créent des segments : pages/admin/formations.vue/admin/formations

3. Technologies Utilisées

Stack Technique

Frontend

TechnologieVersionUsage
Nuxt 34.1.2Framework full-stack
Vue 33.5.22Framework UI
TypeScriptLatestTypage statique
Tailwind CSS6.14Framework CSS utilitaire
Vue Router4.5.1Routing (inclus dans Nuxt)

Backend

TechnologieVersionUsage
NitroInclusServeur backend Nuxt
Supabase JS2.48.1Client base de données
Nodemailer7.0.9Envoi d'emails

Base de Données

TechnologieUsage
SupabasePostgreSQL managé + Storage
PostgreSQLBase de données relationnelle

Outils de Développement

  • pnpm : Gestionnaire de paquets (10.12.1)
  • ESLint : Linter JavaScript/TypeScript
  • Git : Contrôle de version

Charte Graphique

Couleurs

css
/* Couleurs principales */
--brand: #F0D300;        /* Jaune (boutons, accents) */
--text: #2A2C32;         /* Gris foncé (texte) */
--bg: #FCFBF8;           /* Beige clair (fond) */

/* Couleurs badges */
--badge-court: #B9CBFE;  /* Bleu clair (cycle court) */
--badge-long: #B9FEC0;   /* Vert clair (cycle long) */

Typographie

  • Police par défaut : Outfit (Google Fonts)
    • Weights : 300, 400, 500, 600, 700
  • Police titres/logo : Jumper PERSONAL USE ONLY
    • Fichier : public/fonts/Jumper.woff2

4. Fonctionnalités Principales

Pour les Visiteurs

4.1 Consultation des Formations

  • Page : Accueil (/)
  • Fonctionnalités :
    • Affichage dynamique des formations depuis Supabase
    • Filtrage par type (cycle court / cycle long)
    • Cartes avec badges colorés
    • Détails : objectifs, durée, prérequis

4.2 Candidature

  • Page : /candidature
  • Processus :
    1. Étape 1 : Sélection d'une formation
      • Radio buttons avec aperçu complet
      • Badge, titre, descriptions, infos
    2. Étape 2 : Formulaire de candidature
      • Champs obligatoires : Email *, Téléphone *
      • Champs facultatifs : Société, Nom, Prénom, Ville, Adresse
    3. Validation : Envoi email à l'administrateur
    4. Confirmation : Page de remerciement
  • API : POST /api/send-candidature

4.3 Contact

  • Page : /nous-contacter
  • Champs :
    • Obligatoires : Email *, Téléphone *
    • Facultatifs : Société, Nom, Prénom, Ville, Adresse, Message
  • API : POST /api/send-contact

4.4 Financement

  • Page : /financement
  • Sections :
    • Particuliers : CPF, Transitions Pro, Pôle Emploi, Auto-financement
    • Entreprises : OPCO, Plan de développement, Auto-financement
  • Affichage : Onglets avec cartes détaillées
  • API : GET /api/financements

4.5 FAQ

  • Page : /faq
  • Fonctionnalités :
    • Accordéons animés
    • Questions/réponses sur les formations
    • Responsive mobile/desktop

4.6 À Propos

  • Page : /organisme
  • Contenu :
    • Mission de Format IT
    • 4 valeurs : Inclusion, Emploi, Pratique, Impact
    • Certification Qualiopi

Pour les Administrateurs

4.7 Gestion des Formations

  • Page : /admin/formations
  • Fonctionnalités :
    • Liste : Toutes les formations avec aperçu
    • Créer : Nouvelle formation
      • Type (court/long)
      • Badge, titre, couleur
      • Upload image vers Supabase Storage
      • Descriptions multiples (titre + contenu)
      • Infos multiples (titre + contenu)
    • Modifier : Édition formulaire pré-rempli
    • Supprimer : Suppression avec confirmation
  • APIs :
    • GET /api/formations
    • POST /api/formations
    • DELETE /api/formations?id={id}
    • POST /api/upload-image

4.8 Gestion des Financements

  • Page : /admin/financements
  • Fonctionnalités :
    • CRUD options de financement
    • Filtre particuliers/entreprises
    • Édition sections JSON
  • API : POST /api/financements

4.9 Authentification Admin

  • Page : /admin (connexion)
  • Mot de passe : formatit2025
  • Stockage : localStorage (admin_authenticated)
  • Protection : Redirection si non authentifié

5. Configuration

5.1 Fichier nuxt.config.ts

typescript
export default defineNuxtConfig({
  compatibilityDate: '2024-07-15',
  devtools: { enabled: true },

  // Modules
  modules: ['@nuxtjs/tailwindcss'],

  // CSS global
  css: ['~/assets/css/main.css'],

  // Port de développement
  devServer: {
    port: 4000
  },

  // Variables d'environnement
  runtimeConfig: {
    // Variables serveur (privées)
    smtpHost: process.env.SMTP_HOST,
    smtpPort: process.env.SMTP_PORT,
    smtpSecure: process.env.SMTP_SECURE,
    smtpUser: process.env.SMTP_USER,
    smtpPass: process.env.SMTP_PASS,
    smtpFrom: process.env.SMTP_FROM,
    adminEmail: process.env.ADMIN_EMAIL,

    // Variables publiques (accessibles client)
    public: {
      supabaseUrl: process.env.SUPABASE_URL,
      supabaseKey: process.env.SUPABASE_KEY
    }
  },

  // Meta et SEO
  app: {
    head: {
      title: 'Format IT - Transformez votre avenir',
      meta: [
        { charset: 'utf-8' },
        { name: 'viewport', content: 'width=device-width, initial-scale=1' },
        { name: 'description', content: 'Format IT - Organisme de formation professionnelle' }
      ],
      link: [
        { rel: 'icon', type: 'image/png', href: '/img/format-it-logo.png' },
        { rel: 'preconnect', href: 'https://fonts.googleapis.com' },
        {
          rel: 'stylesheet',
          href: 'https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap'
        }
      ]
    }
  }
})

5.2 Variables d'Environnement (.env)

⚠️ IMPORTANT : Le fichier .env ne doit JAMAIS être commité sur Git.

env
# Supabase
SUPABASE_URL=https://kfvjidatbjieiuqpzvix.supabase.co
SUPABASE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# SMTP Google Workspace
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=Administratif@format-it.com
SMTP_PASS=jozh bojp kxqk kbof
SMTP_FROM=Administratif@format-it.com
ADMIN_EMAIL=Administratif@format-it.com

Pour créer votre .env :

bash
cp .env.example .env
# Éditer avec vos vraies credentials

5.3 Configuration Tailwind (tailwind.config.js)

javascript
export default {
  content: [
    "./components/**/*.{js,vue,ts}",
    "./layouts/**/*.vue",
    "./pages/**/*.vue",
    "./plugins/**/*.{js,ts}",
    "./app.vue",
    "./error.vue"
  ],
  theme: {
    extend: {
      colors: {
        'brand': '#F0D300',      // Jaune
        'text': '#2A2C32',       // Gris/Noir
        'bg': '#FCFBF8'          // Beige clair
      },
      fontFamily: {
        'jumper': ['Jumper PERSONAL USE ONLY', 'Arial', 'sans-serif'],
        'outfit': ['Outfit', 'sans-serif']
      }
    }
  },
  plugins: []
}

6. Scripts NPM

6.1 Scripts Disponibles

json
{
  "scripts": {
    "build": "nuxt build",           // Compilation production
    "dev": "nuxt dev",               // Serveur de développement
    "generate": "nuxt generate",     // Génération statique
    "preview": "nuxt preview",       // Preview du build
    "postinstall": "nuxt prepare"    // Auto-exec après install
  }
}

6.2 Commandes Courantes

bash
# Installation des dépendances
pnpm install

# Lancer le serveur de développement
pnpm dev
# → http://localhost:4000

# Build pour la production
pnpm build

# Tester le build en local
pnpm preview

# Script de démarrage rapide
./start.sh

7. APIs et Routes Serveur

7.1 Architecture des APIs

Les APIs suivent la convention file-based routing de Nitro :

  • Fichier : server/api/[nom].[method].ts
  • URL : http://localhost:4000/api/[nom]
  • Méthodes : GET, POST, PUT, DELETE

7.2 Endpoints Disponibles

GET /api/formations

Fichier : server/api/formations.get.ts

Description : Récupère toutes les formations depuis Supabase

Réponse :

typescript
Formation[] // Tableau trié par ID

Code exemple :

typescript
const response = await fetch('/api/formations')
const formations = await response.json()

POST /api/formations

Fichier : server/api/formations.post.ts

Description : Crée ou met à jour des formations

Requête :

typescript
Formation | Formation[]

Logique :

  • Si id existe → UPDATE
  • Sinon → INSERT avec auto-génération d'ID

Réponse :

typescript
{
  success: boolean,
  data?: Formation[]
}

DELETE /api/formations

Fichier : server/api/formations.delete.ts

Description : Supprime une formation

Paramètres : Query ?id={id}

Réponse :

typescript
{
  success: boolean
}

GET /api/financements

Fichier : server/api/financements.get.ts

Description : Récupère les options de financement

Réponse :

typescript
{
  particuliers: FinancementOption[],
  entreprises: FinancementOption[]
}

POST /api/financements

Fichier : server/api/financements.post.ts

Description : Admin - Crée/modifie options de financement

Requête :

typescript
{
  particuliers: FinancementOption[],
  entreprises: FinancementOption[]
}

POST /api/send-candidature

Fichier : server/api/send-candidature.post.ts

Description : Envoie un email de candidature à l'admin

Requête :

typescript
{
  formData: {
    societe?: string,
    nom?: string,
    prenom?: string,
    ville?: string,
    adresse?: string,
    telephone: string,  // Requis
    email: string       // Requis
  },
  formation: {
    badge: string,
    titre: string
  }
}

Validation :

  • Email et téléphone obligatoires
  • Validation format email

Fonctionnement :

  1. Validation des champs requis
  2. Configuration Nodemailer avec SMTP
  3. Génération template HTML élégant
  4. Envoi à ADMIN_EMAIL
  5. Retour { success: true, messageId }

Template Email :

  • En-tête Format IT avec logo
  • Section formation sélectionnée (badge + titre)
  • Informations candidat (affiche uniquement les champs remplis)
  • Footer avec date d'envoi

POST /api/send-contact

Fichier : server/api/send-contact.post.ts

Description : Envoie un email de contact

Requête :

typescript
{
  societe?: string,
  nom?: string,
  prenom?: string,
  ville?: string,
  adresse?: string,
  telephone: string,  // Requis
  email: string,      // Requis
  message?: string
}

Fonctionnement : Similaire à send-candidature

Template Email :

  • Informations de contact (uniquement champs remplis)
  • Message (si présent)
  • Reply-to : email du visiteur

POST /api/upload-image

Fichier : server/api/upload-image.post.ts

Description : Upload une image vers Supabase Storage

Requête : FormData avec file

Fonctionnement :

  1. Validation du fichier (type, taille)
  2. Génération nom unique : formation-{timestamp}.{ext}
  3. Upload dans bucket formation-images
  4. Retour URL publique

Réponse :

typescript
{
  success: boolean,
  url?: string,       // URL publique Supabase
  error?: string
}

Exemple d'utilisation :

javascript
const formData = new FormData()
formData.append('file', imageFile)

const response = await fetch('/api/upload-image', {
  method: 'POST',
  body: formData
})
const { url } = await response.json()

8. Composables

8.1 useFormations.ts

Fichier : composables/useFormations.ts

Description : Gestion centralisée des formations avec Composition API

État Global

typescript
const formations = ref<Formation[]>([])
const loading = ref(false)
const error = ref<string | null>(null)

Type Formation

typescript
interface Formation {
  id: number
  type: 'court' | 'long'
  badge: string              // "Cycle court" ou "Cycle long"
  badgeColor: string         // Couleur hex
  titre: string
  image: string              // URL Supabase
  descriptions: Array<{
    titre: string
    contenu: string
  }>
  infos: Array<{
    titre: string
    contenu: string
  }>
}

Méthodes

loadFormations()
typescript
async loadFormations(): Promise<void>
  • Charge toutes les formations depuis l'API
  • Met à jour formations.value
  • Gère les états loading et error

Usage :

javascript
const { loadFormations, formations } = useFormations()
await loadFormations()

getFormationsByType()
typescript
getFormationsByType(type: 'court' | 'long' | 'tout'): Formation[]
  • Filtre les formations par type
  • 'tout' : retourne toutes les formations

Usage :

javascript
const formationsCourt = getFormationsByType('court')

saveFormations()
typescript
async saveFormations(formationsToSave: Formation[]): Promise<{
  success: boolean
  error?: string
}>
  • Sauvegarde un tableau de formations
  • Appelle POST /api/formations

addFormation()
typescript
async addFormation(formation: Omit<Formation, 'id'>): Promise<{
  success: boolean
  error?: string
}>
  • Ajoute une nouvelle formation
  • ID auto-généré

updateFormation()
typescript
async updateFormation(
  id: number,
  updates: Partial<Formation>
): Promise<{
  success: boolean
  error?: string
}>
  • Met à jour une formation existante

deleteFormation()
typescript
async deleteFormation(id: number): Promise<{
  success: boolean
  error?: string
}>
  • Supprime une formation
  • Appelle DELETE /api/formations?id={id}

9. Composants Vue

9.1 AppHeader.vue

Description : En-tête du site avec navigation

Fonctionnalités :

  • Logo Format IT
  • Navigation desktop : Accueil, Organisme, Financement, Candidatez (CTA)
  • Menu hamburger mobile avec animation
  • Sticky header avec backdrop blur

Props : Aucune


9.2 AppFooter.vue

Description : Pied de page du site

Sections :

  1. Newsletter : Formulaire d'inscription
  2. Coordonnées : Adresse, téléphone
  3. Réseaux sociaux : Facebook, Twitter, LinkedIn
  4. Liens : CGV, Financement, Réclamation, FAQ, Contact, Certificat
  5. Certification : Logo Qualiopi

9.3 AdminNav.vue

Description : Navigation admin

Liens :

  • Formations
  • Financements
  • Déconnexion

Visibilité : Uniquement si authentifié


9.4 FormationCardSkeleton.vue

Description : Placeholder animé pendant le chargement

Utilisation :

vue
<FormationCardSkeleton v-for="n in 6" :key="n" />

9.5 PatternSvg.vue

Description : Décoration SVG pattern en arrière-plan

Fonctionnalités :

  • Pattern répété
  • Mix-blend-mode: darken
  • Position absolute

10. Pages

10.1 Pages Publiques

/ - Accueil

Fichier : pages/index.vue

Sections :

  • Hero avec titre principal "Formez-vous... au monde de demain"
  • Section testimonies avec cartes flottantes
  • CTA "Contacter-nous"

/organisme - À Propos

Fichier : pages/organisme.vue

Contenu :

  • Mission de l'organisme
  • 4 valeurs : Inclusion, Emploi, Pratique, Impact
  • Certification Qualiopi

/faq - Questions Fréquentes

Fichier : pages/faq.vue

Fonctionnalités :

  • Accordéons animés avec transitions smooth
  • Questions sur certifications, rythme, prérequis
  • Responsive

/financement - Options de Financement

Fichier : pages/financement.vue

Fonctionnalités :

  • Onglets : Particuliers / Entreprises
  • Cartes dynamiques depuis API
  • Détails : Pourquoi, Fonctionnement, Avantages
  • Numérotation avec gradient

/candidature - Candidature

Fichier : pages/candidature.vue

Processus Multi-Steps :

Étape 1 : Sélection Formation

  • Cartes formations avec radio buttons
  • Badge, titre, descriptions, infos
  • Validation : formation sélectionnée

Étape 2 : Formulaire

  • Champs obligatoires : Email *, Téléphone *
  • Champs facultatifs : Société, Nom, Prénom, Ville, Adresse
  • Validation avant soumission

Étape 3 : Confirmation

  • Message de remerciement
  • Illustration
  • Bouton "Continuer ma navigation"

Gestion d'État :

javascript
const formData = ref({
  societe: '',
  nom: '',
  prenom: '',
  ville: '',
  adresse: '',
  telephone: '',
  email: ''
})
const selectedFormation = ref<number | null>(null)
const formSubmitted = ref(false)

/nous-contacter - Contact

Fichier : pages/nous-contacter.vue

Formulaire :

  • Champs obligatoires : Email *, Téléphone *
  • Champs facultatifs : Société, Nom, Prénom, Ville, Adresse, Message
  • Validation email
  • Message d'erreur dynamique
  • Page de confirmation

10.2 Pages Admin

/admin - Connexion

Fichier : pages/admin/index.vue

Fonctionnalités :

  • Formulaire de connexion simple
  • Mot de passe : formatit2025
  • Stockage : localStorage.setItem('admin_authenticated', 'true')
  • Redirection automatique si déjà authentifié

/admin/formations - Gestion Formations

Fichier : pages/admin/formations.vue

Fonctionnalités :

Liste :

  • Affichage de toutes les formations
  • Image preview
  • Badge et titre
  • Boutons Modifier / Supprimer

Modal Ajout/Édition :

  • Select type (court/long)
  • Input titre, badge
  • Color picker pour badge
  • Upload image :
    • Sélection fichier
    • Preview
    • Upload vers Supabase Storage
    • URL générée automatiquement
  • Descriptions :
    • Champs dynamiques (titre + contenu)
    • Boutons Ajouter / Supprimer
  • Infos :
    • Champs dynamiques (titre + contenu)
    • Boutons Ajouter / Supprimer
  • Validation formulaire
  • Sauvegarde via useFormations()

Modal Suppression :

  • Confirmation avant suppression
  • Appel deleteFormation(id)

/admin/financements - Gestion Financements

Fichier : pages/admin/financements.vue

Fonctionnalités :

  • CRUD options financement
  • Filtre particuliers/entreprises
  • Édition sections JSON
  • Toggle visibilité

11. Base de Données Supabase

11.1 Configuration

URL : https://kfvjidatbjieiuqpzvix.supabase.co

Client : utils/supabase.ts

typescript
import { createClient } from '@supabase/supabase-js'

const config = useRuntimeConfig()
export const supabase = createClient(
  config.public.supabaseUrl,
  config.public.supabaseKey
)

11.2 Tables

Table formations

Structure :

sql
CREATE TABLE formations (
  id BIGINT PRIMARY KEY,
  type TEXT NOT NULL,           -- 'court' ou 'long'
  badge TEXT NOT NULL,          -- "Cycle court" / "Cycle long"
  badge_color TEXT NOT NULL,    -- Couleur hex
  titre TEXT NOT NULL,
  image TEXT NOT NULL,          -- URL Supabase Storage
  descriptions JSONB NOT NULL,  -- [{titre, contenu}, ...]
  infos JSONB NOT NULL,         -- [{titre, contenu}, ...]
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

Index :

  • type
  • created_at

RLS (Row Level Security) :

  • Read : Public
  • Write/Update/Delete : Open (⚠️ À sécuriser)

Exemple de données :

json
{
  "id": 1,
  "type": "court",
  "badge": "Cycle court",
  "badge_color": "#B9CBFE",
  "titre": "Business Developer initiation à l'IA",
  "image": "https://kfvjidatbjieiuqpzvix.supabase.co/storage/v1/object/public/formation-images/formation-1234567890.png",
  "descriptions": [
    {
      "titre": "Objectifs",
      "contenu": "Intégrer l'IA dans le cycle de vente"
    }
  ],
  "infos": [
    {
      "titre": "Durée",
      "contenu": "14 heures (2 jours)"
    }
  ]
}

Table financements

Structure :

sql
CREATE TABLE financements (
  id SERIAL PRIMARY KEY,
  type TEXT NOT NULL,       -- 'particuliers' ou 'entreprises'
  numero TEXT NOT NULL,     -- '1', '2', '3', '4'
  visible BOOLEAN DEFAULT true,
  titre TEXT NOT NULL,      -- "CPF", "OPCO", etc.
  sections JSONB NOT NULL,  -- [{titre, contenu}, ...]
  created_at TIMESTAMP DEFAULT NOW(),
  updated_at TIMESTAMP DEFAULT NOW()
);

Exemple de données :

json
{
  "id": 1,
  "type": "particuliers",
  "numero": "1",
  "visible": true,
  "titre": "CPF",
  "sections": [
    {
      "titre": "Pourquoi choisir le CPF ?",
      "contenu": "Le Compte Personnel de Formation..."
    },
    {
      "titre": "Comment ça fonctionne ?",
      "contenu": "Connectez-vous à votre espace..."
    }
  ]
}

11.3 Storage

Bucket : formation-images

Configuration :

  • Public : Oui
  • Max file size : 5MB
  • Allowed types : image/png, image/jpeg, image/webp

URL Pattern :

https://kfvjidatbjieiuqpzvix.supabase.co/storage/v1/object/public/formation-images/{filename}

12. Authentification et Sécurité

12.1 Système Actuel

Admin Login

  • Page : /admin
  • Méthode : Mot de passe simple
  • Credentials : formatit2025
  • Stockage : localStorage.setItem('admin_authenticated', 'true')

Protection des Routes

javascript
// Dans pages/admin/*.vue
onMounted(() => {
  const isAuthenticated = localStorage.getItem('admin_authenticated')
  if (!isAuthenticated) {
    navigateTo('/admin')
  }
})

12.2 Problèmes de Sécurité Identifiés

⚠️ ATTENTION : Le système actuel présente des vulnérabilités :

  1. Mot de passe en clair dans le code source
  2. localStorage facilement modifiable via DevTools
  3. RLS Supabase trop permissif (INSERT/UPDATE/DELETE open)
  4. Pas de JWT ou token serveur
  5. Variables sensibles dans vercel.json

12.3 Recommandations de Sécurité

Court terme

javascript
// 1. Ajouter middleware Nuxt
// server/middleware/auth.ts
export default defineEventHandler((event) => {
  const path = event.node.req.url
  if (path?.startsWith('/admin') && path !== '/admin') {
    const auth = getCookie(event, 'admin_token')
    if (!auth) {
      return sendRedirect(event, '/admin')
    }
  }
})

// 2. Utiliser httpOnly cookies au lieu de localStorage
const token = useCookie('admin_token', { httpOnly: true })

Long terme

  • Implémenter Supabase Auth avec email/password
  • Utiliser JWT tokens avec expiration
  • Restreindre RLS policies :
    sql
    -- Exemple RLS restrictif
    CREATE POLICY "Admin only write" ON formations
      FOR ALL
      USING (auth.role() = 'authenticated');
  • Déplacer variables sensibles vers Vercel Secrets
  • Implémenter RBAC (Role-Based Access Control)

13. Déploiement

13.1 Configuration Vercel

Fichier : vercel.json

json
{
  "buildCommand": "pnpm build",
  "outputDirectory": ".output/public",
  "devCommand": "pnpm dev",
  "installCommand": "pnpm install",
  "framework": "nuxtjs"
}

13.2 Variables d'Environnement Vercel

Dashboard Vercel → Settings → Environment Variables

Ajouter :

  • SUPABASE_URL
  • SUPABASE_KEY
  • SMTP_HOST
  • SMTP_PORT
  • SMTP_SECURE
  • SMTP_USER
  • SMTP_PASS
  • SMTP_FROM
  • ADMIN_EMAIL

⚠️ Important : Ne jamais commiter .env sur Git

13.3 Processus de Déploiement

Via GitHub (Recommandé)

  1. Push sur GitHub

    bash
    git add .
    git commit -m "Deploy to Vercel"
    git push origin main
  2. Vercel détecte automatiquement

    • Build avec pnpm build
    • Deploy serverless functions Nitro
  3. URL de production

    • Vercel génère automatiquement
    • Custom domain configurable

Via CLI Vercel

bash
# Installation
npm i -g vercel

# Login
vercel login

# Deploy
vercel

# Production
vercel --prod

13.4 Build Output

.output/
├── public/           # Assets statiques
├── server/           # Fonctions serverless Nitro
└── nitro.json        # Config Nitro

13.5 Vérifications Post-Déploiement

✅ Checklist :

  • [ ] Variables d'environnement configurées
  • [ ] Connexion Supabase fonctionnelle
  • [ ] Envoi d'emails opérationnel
  • [ ] Upload d'images vers Supabase Storage
  • [ ] Admin login fonctionnel
  • [ ] Toutes les pages accessibles
  • [ ] Responsive mobile/desktop
  • [ ] Performance Lighthouse > 90

14. Guide de Démarrage

14.1 Prérequis

  • Node.js : v18 ou supérieur
  • pnpm : v8 ou supérieur
  • Git : Pour le versioning
  • Compte Supabase : Pour la base de données
  • Compte Google Workspace : Pour SMTP (optionnel)

14.2 Installation

bash
# 1. Cloner/Accéder au projet
cd /mnt/d/save/projets/PERSO/nuxt/Format\ IT/format-it-nuxt3

# 2. Installer pnpm (si nécessaire)
npm install -g pnpm

# 3. Installer les dépendances
pnpm install

# 4. Créer le fichier .env
cp .env.example .env

# 5. Éditer .env avec vos credentials
nano .env  # ou votre éditeur préféré

14.3 Configuration Supabase

Créer un Projet Supabase

  1. Aller sur supabase.com
  2. Créer un nouveau projet
  3. Copier URL et anon key
  4. Coller dans .env

Créer les Tables

bash
# Exécuter le script SQL
# Dans Supabase Dashboard → SQL Editor
# Copier le contenu de supabase-setup.sql et exécuter

Créer le Bucket Storage

  1. Storage → New bucket
  2. Nom : formation-images
  3. Public : ✅ Oui
  4. Allowed types : image/*

14.4 Configuration SMTP (Optionnel)

Google Workspace

  1. Activer l'authentification à deux facteurs
  2. Générer un "Mot de passe d'application"
  3. Copier dans .envSMTP_PASS

Autre fournisseur

  • Mettre à jour SMTP_HOST, SMTP_PORT, etc.

14.5 Lancer le Projet

bash
# Démarrage dev server
pnpm dev

# Ouvrir dans le navigateur
# http://localhost:4000

14.6 Accès Admin

URL : http://localhost:4000/admin
Mot de passe : formatit2025

15. Maintenance et Évolutions

15.1 Tâches de Maintenance

Quotidiennes

  • Vérifier les emails de candidature/contact
  • Surveiller les logs Vercel

Hebdomadaires

  • Backup Supabase (automatique)
  • Vérifier les performances (Lighthouse)

Mensuelles

  • Mettre à jour les dépendances :
    bash
    pnpm update
  • Réviser les formations actives
  • Analyser les statistiques (Google Analytics)

15.2 Évolutions Futures Suggérées

Fonctionnalités

Niveau 1 (Court terme)

  • [ ] Authentification admin sécurisée (Supabase Auth)
  • [ ] Dashboard statistiques (candidatures, visites)
  • [ ] Export CSV des candidatures
  • [ ] Système de notifications email admin
  • [ ] Recherche/filtres avancés formations
  • [ ] Newsletter fonctionnelle (intégration Mailchimp/Brevo)

Niveau 2 (Moyen terme)

  • [ ] Espace candidat avec suivi
  • [ ] Calendrier des sessions
  • [ ] Paiement en ligne (Stripe)
  • [ ] Blog/Actualités
  • [ ] Témoignages dynamiques
  • [ ] Multi-langue (i18n)

Niveau 3 (Long terme)

  • [ ] Plateforme e-learning intégrée
  • [ ] Vidéos de présentation formations
  • [ ] Chat support en ligne
  • [ ] Mobile app (React Native/Flutter)
  • [ ] API publique pour partenaires

Améliorations Techniques

Performance

  • [ ] Optimisation images (WebP, lazy loading)
  • [ ] Code splitting avancé
  • [ ] PWA (Progressive Web App)
  • [ ] CDN pour assets statiques

SEO

  • [ ] Meta tags dynamiques par page
  • [ ] Schema.org markup
  • [ ] Sitemap XML
  • [ ] Open Graph pour réseaux sociaux

Sécurité

  • [ ] Middleware auth robuste
  • [ ] Rate limiting APIs
  • [ ] CSRF protection
  • [ ] Headers sécurité (CSP, HSTS)
  • [ ] Audit sécurité régulier

Tests

  • [ ] Tests unitaires (Vitest)
  • [ ] Tests E2E (Playwright)
  • [ ] CI/CD GitHub Actions
  • [ ] Coverage > 80%

15.3 Gestion des Bugs

Processus

  1. Reproduction : Documenter les étapes
  2. Priorité : Critical / High / Medium / Low
  3. Fix : Créer une branche dédiée
  4. Test : Vérifier localement
  5. Deploy : Merge + déploiement

Outils Recommandés

  • Sentry : Monitoring erreurs
  • LogRocket : Session replay
  • GitHub Issues : Tracking bugs

15.4 Documentation du Code

Conventions

Nommage :

typescript
// Composants : PascalCase
AppHeader.vue

// Pages : kebab-case
nous-contacter.vue

// Variables : camelCase
const formData = ref({})

// Constantes : UPPER_SNAKE_CASE
const API_BASE_URL = '/api'

Commentaires :

typescript
// ✅ Bon
/**
 * Envoie un email de candidature à l'admin
 * @param formData - Données du formulaire
 * @param formation - Formation sélectionnée
 * @returns Promise avec status et messageId
 */
async function sendCandidature(formData, formation) {}

// ❌ Éviter
// Fonction qui envoie email
async function sendCandidature() {}

15.5 Contacts et Support

Équipe Projet

Ressources


Annexes

A. Glossaire

  • Nuxt : Framework Vue.js full-stack
  • Nitro : Moteur serveur de Nuxt
  • Supabase : Backend-as-a-Service (PostgreSQL + Storage)
  • RLS : Row Level Security (sécurité au niveau ligne)
  • SSR : Server-Side Rendering
  • SMTP : Simple Mail Transfer Protocol
  • CRUD : Create, Read, Update, Delete
  • JWT : JSON Web Token

B. Commandes Git

bash
# Status
git status

# Commit
git add .
git commit -m "feat: ajouter nouvelle fonctionnalité"

# Push
git push origin main

# Pull
git pull origin main

# Branches
git checkout -b feature/nouvelle-fonctionnalite
git merge feature/nouvelle-fonctionnalite

C. Dépannage

Le serveur ne démarre pas

bash
# Vérifier Node.js
node -v  # Doit être >= 18

# Nettoyer node_modules
rm -rf node_modules .nuxt
pnpm install

# Vérifier .env
cat .env

Erreur de connexion Supabase

  • Vérifier SUPABASE_URL et SUPABASE_KEY
  • Tester dans Supabase Dashboard
  • Vérifier les RLS policies

Emails non envoyés

  • Vérifier credentials SMTP
  • Tester avec un email de test
  • Consulter les logs Vercel

Version : 1.0 Date : Janvier 2025 Auteur : Équipe Format IT


Cette documentation est un document vivant. N'hésitez pas à la mettre à jour au fur et à mesure des évolutions du projet.

Documentation Format IT