add seo
This commit is contained in:
parent
8be3338265
commit
5e540dc0bb
241
CLAUDE.md
Normal file
241
CLAUDE.md
Normal file
@ -0,0 +1,241 @@
|
||||
# REBOURS — Documentation technique
|
||||
|
||||
## Architecture du projet
|
||||
|
||||
```
|
||||
rebours/
|
||||
├── src/
|
||||
│ ├── layouts/
|
||||
│ │ └── Base.astro # Layout HTML commun (SEO, fonts, CSS)
|
||||
│ └── pages/
|
||||
│ ├── index.astro # Page principale (hero, collection, newsletter)
|
||||
│ ├── collection/
|
||||
│ │ └── [slug].astro # Pages produits statiques (SSG)
|
||||
│ └── success.astro # Page de confirmation Stripe
|
||||
├── public/
|
||||
│ ├── style.css # CSS global
|
||||
│ ├── main.js # JS client (cursor, grid, panel, routing)
|
||||
│ ├── robots.txt # SEO
|
||||
│ ├── sitemap.xml # SEO
|
||||
│ └── assets/ # Images produits
|
||||
├── server.mjs # Serveur API Fastify (Stripe)
|
||||
├── astro.config.mjs # Config Astro (SSG, proxy dev)
|
||||
├── nginx.conf # Config nginx de référence
|
||||
└── .env # Variables d'environnement (non versionné)
|
||||
```
|
||||
|
||||
## Stack
|
||||
|
||||
| Couche | Techno |
|
||||
|--------|--------|
|
||||
| Front (SSG) | Astro + HTML/CSS/JS vanilla |
|
||||
| API | Fastify (Node.js) |
|
||||
| Paiement | Stripe Checkout |
|
||||
| Reverse proxy | Nginx |
|
||||
| Hébergement | VPS (Debian) |
|
||||
| Fonts | Space Mono (Google Fonts) |
|
||||
|
||||
---
|
||||
|
||||
## Développement local
|
||||
|
||||
### Prérequis
|
||||
- Node.js ≥ 18
|
||||
- Un fichier `.env` à la racine (voir `.env.example`)
|
||||
|
||||
### Variables d'environnement (.env)
|
||||
```env
|
||||
STRIPE_SECRET_KEY=sk_test_...
|
||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||
DOMAIN=http://localhost:4321
|
||||
PORT=8888
|
||||
```
|
||||
|
||||
> En dev, le serveur Fastify tourne sur le port **8888** (pour ne pas entrer en conflit avec d'autres services).
|
||||
> Le proxy Vite dans `astro.config.mjs` redirige `/api/*` → `http://127.0.0.1:8888`.
|
||||
|
||||
### Lancer le projet
|
||||
```bash
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
Cela lance en parallèle (via `concurrently`) :
|
||||
- `astro dev` → http://localhost:4321
|
||||
- `node --watch server.mjs` (mode dev, PORT=8888)
|
||||
|
||||
### Build
|
||||
```bash
|
||||
npm run build
|
||||
# Génère ./dist/ (fichiers statiques Astro)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Production
|
||||
|
||||
### Serveur : ordinarthur@10.10.0.13
|
||||
|
||||
### Architecture prod
|
||||
```
|
||||
Internet → Nginx (port 80) → /var/www/html/rebours/dist/ (fichiers statiques)
|
||||
→ /api/* → proxy → Fastify :3000
|
||||
```
|
||||
|
||||
### Chemins importants sur le serveur
|
||||
| Quoi | Où |
|
||||
|------|----|
|
||||
| Fichiers web | `/var/www/html/rebours/dist/` |
|
||||
| Projet complet | `/var/www/html/rebours/` |
|
||||
| Config nginx | `/etc/nginx/sites-available/rebours` |
|
||||
| Service systemd | `rebours.service` |
|
||||
| Logs | `journalctl -u rebours -f` |
|
||||
|
||||
### Variables d'environnement en prod
|
||||
Le fichier `.env` est dans `/var/www/html/rebours/.env` :
|
||||
```env
|
||||
STRIPE_SECRET_KEY=sk_live_...
|
||||
STRIPE_WEBHOOK_SECRET=whsec_...
|
||||
DOMAIN=https://rebours.studio
|
||||
PORT=3000
|
||||
```
|
||||
|
||||
### Service systemd
|
||||
Le serveur Fastify est géré par systemd :
|
||||
```bash
|
||||
sudo systemctl status rebours
|
||||
sudo systemctl restart rebours
|
||||
sudo systemctl stop rebours
|
||||
journalctl -u rebours -f # logs en temps réel
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Déploiement (mise à jour du site)
|
||||
|
||||
### 1. Build en local
|
||||
```bash
|
||||
npm run build
|
||||
# Génère ./dist/
|
||||
```
|
||||
|
||||
### 2. Envoyer les fichiers sur le serveur
|
||||
|
||||
Les fichiers statiques Astro :
|
||||
```bash
|
||||
scp -r dist/* ordinarthur@10.10.0.13:/tmp/rebours-dist/
|
||||
ssh ordinarthur@10.10.0.13 "sudo cp -r /tmp/rebours-dist/* /var/www/html/rebours/dist/"
|
||||
```
|
||||
|
||||
Si le server.mjs a changé :
|
||||
```bash
|
||||
scp server.mjs ordinarthur@10.10.0.13:/tmp/server.mjs
|
||||
ssh ordinarthur@10.10.0.13 "sudo cp /tmp/server.mjs /var/www/html/rebours/server.mjs && sudo systemctl restart rebours"
|
||||
```
|
||||
|
||||
### 3. Vérifier
|
||||
```bash
|
||||
ssh ordinarthur@10.10.0.13 "sudo nginx -t && sudo systemctl status rebours"
|
||||
```
|
||||
|
||||
### Permissions (si problème 403 nginx)
|
||||
```bash
|
||||
ssh ordinarthur@10.10.0.13 "sudo chown -R www-data:www-data /var/www/html/rebours/dist"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nginx — référence
|
||||
|
||||
Le fichier `nginx.conf` à la racine du projet est la config de **référence**.
|
||||
La config réelle sur le serveur est dans `/etc/nginx/sites-available/rebours`.
|
||||
|
||||
Pour mettre à jour la config nginx :
|
||||
```bash
|
||||
scp nginx.conf ordinarthur@10.10.0.13:/tmp/nginx-rebours.conf
|
||||
ssh ordinarthur@10.10.0.13 "sudo cp /tmp/nginx-rebours.conf /etc/nginx/sites-available/rebours && sudo nginx -t && sudo systemctl reload nginx"
|
||||
```
|
||||
|
||||
Points clés de la config :
|
||||
- `root /var/www/html/rebours/dist` → fichiers statiques Astro
|
||||
- `try_files $uri $uri/ $uri.html /index.html` → SPA fallback pour les routes Astro
|
||||
- `/api/` → proxy vers Fastify sur `127.0.0.1:3000`
|
||||
- HTML : `no-store` (jamais caché)
|
||||
- CSS/JS/assets : `immutable` (hash dans le nom de fichier, cache 1 an)
|
||||
|
||||
---
|
||||
|
||||
## Routing
|
||||
|
||||
Le routing est hybride :
|
||||
|
||||
| URL | Comportement |
|
||||
|-----|-------------|
|
||||
| `/` | Page principale Astro |
|
||||
| `/collection/lumiere-orbitale` | Page Astro SSG générée statiquement, ouvre le panel auto via `window.__OPEN_PANEL__` |
|
||||
| `/collection/table-terrazzo` | idem |
|
||||
| `/collection/module-serie` | idem |
|
||||
| `/success?session_id=...` | Page de confirmation Stripe |
|
||||
|
||||
Quand on clique sur une carte produit depuis le navigateur (sans refresh) :
|
||||
- Le panel s'ouvre
|
||||
- `history.pushState` change l'URL → `/collection/{slug}`
|
||||
- Le bouton retour du navigateur ferme le panel et revient à `/`
|
||||
|
||||
Quand on arrive directement sur `/collection/{slug}` (lien partagé, refresh) :
|
||||
- Astro sert la page statique correspondante
|
||||
- Un script inline lit `<meta name="x-open-panel">` et set `window.__OPEN_PANEL__`
|
||||
- `main.js` lit `window.__OPEN_PANEL__` au DOMContentLoaded et ouvre le bon panel
|
||||
|
||||
---
|
||||
|
||||
## Ajouter un produit
|
||||
|
||||
### 1. Ajouter la carte dans `src/pages/index.astro` et `src/pages/collection/[slug].astro`
|
||||
Copier un `<article class="product-card">` existant et modifier les `data-*`.
|
||||
|
||||
### 2. Ajouter le slug dans `[slug].astro`
|
||||
Dans `getStaticPaths()`, ajouter une entrée dans le tableau `PRODUCTS` :
|
||||
```js
|
||||
{
|
||||
slug: 'mon-nouveau-produit',
|
||||
name: 'MON_PRODUIT',
|
||||
title: 'REBOURS — Mon Produit | Collection 001',
|
||||
description: 'Description pour le SEO.',
|
||||
ogImage: 'https://rebours.studio/assets/mon-produit.jpg',
|
||||
},
|
||||
```
|
||||
|
||||
### 3. Ajouter l'image dans `public/assets/`
|
||||
Format recommandé : JPG 1024×1024, < 300 Ko.
|
||||
|
||||
### 4. Ajouter le prix Stripe dans `server.mjs`
|
||||
```js
|
||||
const PRODUCTS = {
|
||||
lumiere_orbitale: { price_id: 'price_xxx' },
|
||||
mon_nouveau_produit: { price_id: 'price_yyy' }, // ← ajouter
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Rebuild et déployer
|
||||
```bash
|
||||
npm run build
|
||||
# puis déployer (voir section Déploiement)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Stripe
|
||||
|
||||
- **Test** : utiliser les clés `sk_test_...` dans `.env`
|
||||
- **Prod** : utiliser les clés `sk_live_...` dans `.env` sur le serveur
|
||||
- La redirection après paiement va vers `${DOMAIN}/success?session_id=...`
|
||||
- Le webhook Stripe doit pointer vers `https://rebours.studio/api/webhook`
|
||||
- Le `STRIPE_WEBHOOK_SECRET` correspond au secret généré dans le dashboard Stripe pour ce webhook
|
||||
|
||||
---
|
||||
|
||||
## Fichiers à ne jamais versionner
|
||||
- `.env` (clés Stripe, secrets)
|
||||
- `node_modules/`
|
||||
- `dist/` (généré par le build)
|
||||
5
public/robots.txt
Normal file
5
public/robots.txt
Normal file
@ -0,0 +1,5 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
Disallow: /success
|
||||
|
||||
Sitemap: https://rebours.studio/sitemap.xml
|
||||
27
public/sitemap.xml
Normal file
27
public/sitemap.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://rebours.studio/</loc>
|
||||
<lastmod>2026-02-27</lastmod>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rebours.studio/collection/lumiere-orbitale/</loc>
|
||||
<lastmod>2026-02-27</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rebours.studio/collection/table-terrazzo/</loc>
|
||||
<lastmod>2026-02-27</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://rebours.studio/collection/module-serie/</loc>
|
||||
<lastmod>2026-02-27</lastmod>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.9</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
@ -10,7 +10,7 @@ const {
|
||||
title,
|
||||
description = 'REBOUR Studio crée du mobilier d\'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours.',
|
||||
ogImage = 'https://rebours.studio/assets/lamp-violet.jpg',
|
||||
canonical = 'https://rebour.studio/',
|
||||
canonical = 'https://rebours.studio/',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
|
||||
@ -9,6 +9,9 @@ export function getStaticPaths() {
|
||||
title: 'REBOURS — Solar Altar | Collection 001',
|
||||
description: 'Lampe de table unique. Béton texturé coulé à la main + dôme céramique laqué. Pièce unique fabriquée à Paris.',
|
||||
ogImage: 'https://rebours.studio/assets/lamp-violet.jpg',
|
||||
productName: 'Solar Altar',
|
||||
price: '1800',
|
||||
availability: 'https://schema.org/LimitedAvailability',
|
||||
},
|
||||
{
|
||||
slug: 'table-terrazzo',
|
||||
@ -16,6 +19,9 @@ export function getStaticPaths() {
|
||||
title: 'REBOURS — TABLE TERRAZZO | Collection 001',
|
||||
description: 'Table basse et étagère modulaire. Terrazzo fait main + acier tubulaire. Pièce unique fabriquée à Paris.',
|
||||
ogImage: 'https://rebours.studio/assets/table-terrazzo.jpg',
|
||||
productName: 'Table Terrazzo',
|
||||
price: null,
|
||||
availability: 'https://schema.org/PreOrder',
|
||||
},
|
||||
{
|
||||
slug: 'module-serie',
|
||||
@ -23,20 +29,57 @@ export function getStaticPaths() {
|
||||
title: 'REBOURS — MODULE SÉRIE | Collection 001',
|
||||
description: 'Série de 7 lampes béton colorées, dôme laqué et néon. Édition limitée fabriquée à Paris.',
|
||||
ogImage: 'https://rebours.studio/assets/lampes-serie.jpg',
|
||||
productName: 'Module Série',
|
||||
price: null,
|
||||
availability: 'https://schema.org/PreOrder',
|
||||
},
|
||||
];
|
||||
return PRODUCTS.map(p => ({ params: { slug: p.slug }, props: p }));
|
||||
}
|
||||
|
||||
const { slug, title, description, ogImage, name } = Astro.props;
|
||||
const { slug, title, description, ogImage, name, productName, price, availability } = Astro.props;
|
||||
|
||||
const schemaProduct = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Product",
|
||||
"name": productName,
|
||||
"description": description,
|
||||
"image": ogImage,
|
||||
"brand": { "@type": "Brand", "name": "REBOURS Studio" },
|
||||
"url": `https://rebours.studio/collection/${slug}/`,
|
||||
...(price ? {
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": price,
|
||||
"priceCurrency": "EUR",
|
||||
"availability": availability,
|
||||
"seller": { "@type": "Organization", "name": "REBOURS Studio" }
|
||||
}
|
||||
} : {}),
|
||||
};
|
||||
|
||||
const schemaBreadcrumb = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{ "@type": "ListItem", "position": 1, "name": "Accueil", "item": "https://rebours.studio/" },
|
||||
{ "@type": "ListItem", "position": 2, "name": "Collection 001", "item": "https://rebours.studio/#collection" },
|
||||
{ "@type": "ListItem", "position": 3, "name": productName, "item": `https://rebours.studio/collection/${slug}/` },
|
||||
]
|
||||
};
|
||||
---
|
||||
|
||||
<Base
|
||||
title={title}
|
||||
description={description}
|
||||
ogImage={ogImage}
|
||||
canonical={`https://rebour.studio/collection/${slug}`}
|
||||
canonical={`https://rebours.studio/collection/${slug}/`}
|
||||
>
|
||||
<Fragment slot="head">
|
||||
<script type="application/ld+json" set:html={JSON.stringify(schemaProduct)} />
|
||||
<script type="application/ld+json" set:html={JSON.stringify(schemaBreadcrumb)} />
|
||||
</Fragment>
|
||||
|
||||
<!-- On charge index.html entier et on ouvre le panel via JS au load -->
|
||||
<meta name="x-open-panel" content={name} />
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ const schemaOrg = {
|
||||
"@type": "Store",
|
||||
"name": "REBOURS Studio",
|
||||
"description": "Mobilier d'art contemporain. Space Age × Memphis. Pièces uniques fabriquées à Paris.",
|
||||
"url": "https://rebours.studio",
|
||||
"url": "https://rebours.studio/",
|
||||
"image": "https://rebours.studio/assets/lamp-violet.jpg",
|
||||
"address": { "@type": "PostalAddress", "addressLocality": "Paris", "addressCountry": "FR" },
|
||||
"hasOfferCatalog": {
|
||||
@ -31,7 +31,7 @@ const schemaOrg = {
|
||||
<Base
|
||||
title="REBOURS — Mobilier d'art contemporain | Collection 001"
|
||||
description="REBOUR Studio crée du mobilier d'art contemporain inspiré du Space Age et du mouvement Memphis. Pièces uniques fabriquées à Paris. Collection 001 en cours."
|
||||
canonical="https://rebour.studio/"
|
||||
canonical="https://rebours.studio/"
|
||||
>
|
||||
<Fragment slot="head">
|
||||
<script type="application/ld+json" set:html={JSON.stringify(schemaOrg)} />
|
||||
|
||||
@ -3,10 +3,11 @@ import Base from '../layouts/Base.astro';
|
||||
---
|
||||
|
||||
<Base
|
||||
title="REBOUR — COMMANDE CONFIRMÉE"
|
||||
title="REBOURS — COMMANDE CONFIRMÉE"
|
||||
description="Votre commande REBOURS Studio a été confirmée."
|
||||
canonical="https://rebour.studio/success"
|
||||
canonical="https://rebours.studio/success"
|
||||
>
|
||||
<meta name="robots" content="noindex, nofollow" slot="head">
|
||||
<style>
|
||||
main {
|
||||
flex-grow: 1;
|
||||
@ -91,7 +92,7 @@ import Base from '../layouts/Base.astro';
|
||||
|
||||
<main>
|
||||
<div class="left">
|
||||
<img id="product-img" class="product-img" src="/assets/lamp-violet.jpg" alt="">
|
||||
<img id="product-img" class="product-img" src="/assets/lamp-violet.jpg" alt="Produit REBOURS Studio">
|
||||
<p class="slabel" style="position:relative">// COMMANDE_CONFIRMÉE</p>
|
||||
<h1 style="position:relative">MERCI<br>POUR<br>VOTRE<br>COMMANDE</h1>
|
||||
<p class="status-line" id="loading" style="position:relative">Vérification du paiement...</p>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user