🗼 Documentation
week-end in Paris — Guide technique complet
Présentation du projet
Weekend in Paris est un site de tourisme parisien proposant un agenda d'événements culturels, sportifs et gastronomiques, une carte des attractions incontournables et une sélection de restaurants. Le site est multilingue (FR / EN / ZH) et entièrement responsive.
🌐 https://weekend-in-paris.vercel.app
| Élément | Valeur |
|---|---|
| URL | https://weekend-in-paris.vercel.app |
| Framework | Next.js 14 (Pages Router) |
| Base de données | Supabase (PostgreSQL) |
| Cartes interactives | Mapbox GL 3 |
| Hébergement | Vercel (plan Hobby) |
| Dépôt GitHub | fl3m-ia |
| Email GitHub / Vercel | fl3m.ia@gmail.com |
| Langues supportées | 🇫🇷 Français, 🇬🇧 Anglais, 🇨🇳 Chinois |
| Nombre d'événements | 50 (avril – juin 2026) |
Architecture & Stack technique
Vue d'ensemble
Weekend in Paris est développé avec Next.js 14 (Pages Router) et déployé sur Vercel. Il présente les événements, attractions et restaurants de Paris avec des cartes interactives et un système multilingue.
⚛️ Front-end
- Next.js 14
- Framework React avec rendu hybride (SSG + ISR)
- React 18
- Bibliothèque UI
- Tailwind CSS 3
- Design responsive, couleurs personnalisées
- Mapbox GL 3
- Cartes interactives (événements + attractions)
🗄️ Back-end / Data
- Supabase
- Base de données PostgreSQL hébergée + client JS
- Données statiques
- Événements codés dans pages/index.jsx
- Données dynamiques
- Attractions & restaurants via getStaticProps + ISR
- Vercel
- Hébergement + CI/CD automatique sur push GitHub
Structure des dossiers
01_weekend_in_paris/
├── components/ # Composants React réutilisables
│ ├── Header.jsx # Navigation + logo bannière
│ ├── Footer.jsx # Pied de page
│ ├── AttractionCard.jsx
│ ├── Gallery.jsx # Galerie photo
│ ├── Map.jsx # Carte Mapbox (attractions)
│ └── MapEvents.jsx # Carte Mapbox (événements)
├── context/
│ └── LanguageContext.jsx # Gestion i18n (FR / EN / ZH)
├── data/
│ └── parisImages.js # URLs d'images (Pexels/Pixabay)
├── lib/
│ └── supabaseClient.js # Client Supabase + fonctions CRUD
├── pages/ # Pages Next.js
│ ├── _app.jsx
│ ├── _document.jsx
│ ├── index.jsx # Accueil — événements + galerie + carte
│ ├── attractions.jsx
│ ├── restaurants.jsx
│ └── api/seed.js
├── public/
│ ├── locales/ # Fichiers de traduction (fr, en, zh)
│ ├── logo_banner.jpg # Logo paysage (header du site)
│ └── logo_portrait.jpg # Logo portrait (Instagram)
├── scripts/
│ └── seedDatabase.js # Peuplement Supabase
├── .env.local # Variables d'environnement
├── next.config.js
└── tailwind.config.jsCouleurs du thème (Tailwind)
| Nom | Hex | Usage |
|---|---|---|
paris-gold | #D4AF37 | Boutons, badges, accents |
paris-dark | #1a1a1a | Texte principal |
paris-light | #f5f5f5 | Fonds clairs |
Pages du site
Accueil
- Hero section — Titre en grand avec fond photographique Paris
- Bannière événements — Gradient rose→violet avec titre et sous-titre i18n
- Filtres par catégorie — 11 catégories : culturel, musique, cinéma, festival…
- Carte Mapbox interactive — Géolocalisation de tous les événements filtrés
- Grille d'événements — Affichage en 3 colonnes avec image, dates, lieu, tarif
- Galerie photo — Composant Gallery.jsx avec images de Paris
index.jsx (tableau EVENT_DATA de 50 événements couvrant avril–juin 2026). Les libellés sont internationalisés via le système i18n.Attractions
- Hero section — gradient bleu→violet
- Carte Mapbox — localisation de toutes les attractions
- Filtres — monument, musée, parc, shopping
- Grille d'attractions — composant AttractionCard
attractions), récupérées via getStaticProps avec revalidation ISR toutes les heures.Restaurants
- Hero section — gradient orange→rouge
- Filtres par cuisine — français, asiatique, italien, fusion
- Grille de restaurants — nom, description, localisation, cuisine, note, fourchette de prix
restaurants), même pattern ISR.Composants principaux
| Composant | Rôle |
|---|---|
| Header.jsx | Navigation sticky, logo bannière, sélecteur de langue |
| Footer.jsx | Pied de page avec liens et infos |
| AttractionCard.jsx | Carte d'une attraction touristique |
| Gallery.jsx | Galerie photo interactive |
| Map.jsx | Carte Mapbox pour la page Attractions |
| MapEvents.jsx | Carte Mapbox pour la page Accueil (événements) |
Catégories d'événements
| Emoji | Catégorie | Description |
|---|---|---|
| 🎭 | culturel | Expositions, musées, danse |
| 🎵 | musique | Concerts, opéras |
| 🎬 | cinéma | Projections, rétrospectives |
| 🎪 | festival | Festivals thématiques |
| 🍽️ | gastronomie | Salons, marchés, fêtes culinaires |
| 🏃 | sport | Marathons, rollers, compétitions |
| 🎮 | pop culture | Comic Con, jeux vidéo |
| 🎡 | loisirs | Marchés, croisières, parcs |
| 🏛️ | patrimoine | Monuments, nuit des musées |
| ⭐ | spécial | Événements uniques (Fashion Week, etc.) |
Base de données Supabase
Le projet utilise Supabase comme base de données PostgreSQL et comme API REST. Le client est initialisé dans lib/supabaseClient.js.
Table attractions
| Colonne | Type | Description |
|---|---|---|
| id | BIGINT (PK, auto) | Identifiant unique |
| name | VARCHAR(255) | Nom de l'attraction |
| description | TEXT | Description |
| location | VARCHAR(255) | Adresse courte |
| latitude | DECIMAL(10,8) | Latitude GPS |
| longitude | DECIMAL(11,8) | Longitude GPS |
| image_url | VARCHAR(500) | URL de l'image |
| rating | DECIMAL(2,1) | Note (ex: 4.8) |
| category | VARCHAR(50) | monument / musée / parc / shopping |
| opening_hours | VARCHAR(255) | Horaires d'ouverture |
| entrance_fee | VARCHAR(100) | Tarif d'entrée |
| website | VARCHAR(500) | Site officiel |
| created_at | TIMESTAMP | Date de création |
Table restaurants
| Colonne | Type | Description |
|---|---|---|
| id | BIGINT (PK, auto) | Identifiant unique |
| name | VARCHAR(255) | Nom du restaurant |
| description | TEXT | Description |
| location | VARCHAR(255) | Adresse |
| latitude | DECIMAL(10,8) | Latitude GPS |
| longitude | DECIMAL(11,8) | Longitude GPS |
| image | VARCHAR(500) | URL de l'image |
| cuisine | VARCHAR(50) | français / asiatique / italien / fusion |
| rating | DECIMAL(2,1) | Note |
| price_range | VARCHAR(50) | Ex: €€€€ |
| phone | VARCHAR(20) | Téléphone |
| website | VARCHAR(500) | Site officiel |
| created_at | TIMESTAMP | Date de création |
Table contacts
| Colonne | Type | Description |
|---|---|---|
| id | BIGINT (PK, auto) | Identifiant unique |
| name | VARCHAR(255) | Nom de l'expéditeur |
| VARCHAR(255) | ||
| subject | VARCHAR(255) | Sujet |
| message | TEXT | Message |
| submitted_at | TIMESTAMP | Date d'envoi |
| created_at | TIMESTAMP | Date de création |
Fonctions disponibles
Fichier : lib/supabaseClient.js
// Récupérer toutes les attractions triées par note
getAttractions()
// Récupérer une attraction par son ID
getAttractionById(id)
// Récupérer tous les restaurants
getRestaurants()
// Soumettre un formulaire de contact
submitContact(contactData)Seeding de la base
⚠️ Important : Le seeding doit être exécuté depuis la machine locale (pas depuis Vercel). Il lit .env.local pour se connecter à Supabase.
# Depuis le dossier du projet
cd /Users/fl3m/Documents/Claude/Projects/01_weekend_in_paris
node scripts/seedDatabase.jsInternationalisation (i18n)
Le site supporte 3 langues. La langue par défaut est le français. Le choix est persisté dans localStorage.
| Code | Langue | Fichier |
|---|---|---|
| fr | 🇫🇷 Français | public/locales/fr.json |
| en | 🇬🇧 Anglais | public/locales/en.json |
| zh | 🇨🇳 Chinois | public/locales/zh.json |
Implémentation
Le système est géré par context/LanguageContext.jsx qui expose :
- LanguageProvider — wrapper à placer dans
_app.jsx, charge le fichier JSON de la langue sélectionnée - useLanguage() — hook donnant accès à
languageetswitchLanguage(lang) - useTranslation() — hook qui retourne la fonction
t(key)
import { useTranslation } from '../context/LanguageContext';
export default function MyComponent() {
const { t } = useTranslation();
return <h1>{t('home.hero_title')}</h1>;
}Structure des fichiers de traduction
{
"home": {
"title": "...",
"hero_title": "...",
"hero_subtitle": "..."
},
"evenements": {
"hero_title": "...",
"all": "Tous",
"culturel": "Culturel",
"events": {
"foire_du_trone": {
"title": "...",
"dates": "...",
"lieu": "...",
"address": "...",
"description": "...",
"tarif": "..."
}
}
}
}ℹ️ Chaque événement dans EVENT_DATA a un slug qui correspond à une clé dans evenements.events. Les 50 événements sont tous traduits en FR, EN et ZH.
Déploiement (Vercel + GitHub)
| Élément | Valeur |
|---|---|
| URL de production | https://weekend-in-paris.vercel.app |
| Plateforme | Vercel (plan Hobby) |
| Branche suivie | main |
| Compte GitHub | fl3m-ia |
| Email GitHub/Vercel | fl3m.ia@gmail.com |
| Framework détecté | Next.js |
Processus de déploiement
Development (local)
↓
git push origin main
↓
GitHub (fl3m-ia/weekend-in-paris)
↓
Vercel (détection automatique)
↓
Build Next.js (npm run build)
↓
Production : https://weekend-in-paris.vercel.appCommandes git importantes
⚠️ Utiliser uniquement fl3m.ia@gmail.com comme email git. Un autre email provoque le blocage du déploiement par Vercel.
# Configuration obligatoire avant tout commit
git config user.email 'fl3m.ia@gmail.com'
git config user.name 'fl3m-ia'
# Déployer une modification
git add <fichiers>
git commit -m "description du changement"
git push origin mainVariables d'environnement (Vercel)
| Variable | Description |
|---|---|
| NEXT_PUBLIC_SUPABASE_URL | URL du projet Supabase |
| NEXT_PUBLIC_SUPABASE_ANON_KEY | Clé anonyme Supabase |
| NEXT_PUBLIC_MAPBOX_TOKEN | Token d'accès Mapbox GL |
Guide de développement local
Prérequis
- Node.js 18+
- npm
- Un compte Supabase (gratuit)
- Un token Mapbox (gratuit)
Installation
# 1. Se placer dans le dossier du projet
cd /Users/fl3m/Documents/Claude/Projects/01_weekend_in_paris
# 2. Installer les dépendances
npm install
# 3. Lancer le serveur de développement
npm run dev
# 4. Ouvrir dans le navigateur
open http://localhost:3000Fichier .env.local
NEXT_PUBLIC_SUPABASE_URL=https://xxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...
NEXT_PUBLIC_MAPBOX_TOKEN=pk.eyJ1IjoiZmwz...Scripts npm
| Commande | Description |
|---|---|
| npm run dev | Lance le serveur de développement (port 3000) |
| npm run build | Compile l'application pour la production |
| npm run start | Lance le serveur de production en local |
| npm run lint | Vérifie le code avec ESLint |
Ajouter un nouvel événement
1. Ajouter l'objet dans le tableau EVENT_DATA de pages/index.jsx :
{
id: 51,
slug: 'mon_evenement',
category: 'culturel',
dateStart: '2026-07-14',
icon: '🇫🇷',
image: parisImages.art,
longitude: 2.3376,
latitude: 48.8606,
link: 'https://...'
}2. Ajouter les traductions dans les 3 fichiers de locales sous la clé evenements.events.mon_evenement :
"mon_evenement": {
"title": "Mon Événement",
"dates": "14 juillet 2026",
"lieu": "Champs-Élysées",
"address": "Avenue des Champs-Élysées, 75008 Paris",
"description": "Description de l'événement...",
"tarif": "Gratuit"
}3. Committer et pousser → Vercel redéploie automatiquement.