Conventions — Site Marketing
Standards de code et d'organisation adoptés dans le projet aurora-home-marketing.
Stack technique
Nuxt 4Framework fullstack Vue — routing fichier, SSR, backend NitroVue 3Composition API — réactivité, composables, slotsTypeScript 5Mode strict — noImplicitAny, strictNullChecks, noUncheckedIndexedAccessTailwind CSS v4CSS utilitaire v4 — layers personnalisés (glass-panel, glass-button, glass-input)Three.jsViewer 3D produit — OBJ loader, OrbitControls, export GLTF + ARPiniaGestion d'état — store panier persisté en localStorageStripePaiement en ligne — PaymentIntent serveur + Elements clientChart.js + vue-chartjsGraphiques admin — ventes par jour (Bar chart via vue-chartjs)better-sqlite3Base de données embarquée — transactions atomiques via better-sqlite3Phosphor IconsBibliothèque d'icônes (CDN)ESLint + HuskyLinting + Husky pre-commit hookStructure des dossiers
Conventions de nommage
kebab-case + method suffixcart.tsmain.cssindex.get.tsconfirm.post.ts[id].put.tsPascalCaseTheHeader.vueTheFooter.vueLiquidGlass.vueProduct3DViewer.client.vueuse* camelCaseuseCartStoreuseRouter()useRuntimeConfig()addItem()isProcessingComposants client-only
Les composants qui accèdent aux APIs navigateur (WebGL, canvas, window) sont suffixés .client.vue. Nuxt les exclut automatiquement du rendu SSR.
// Suffixe .client.vue → Nuxt exclut ce composant du SSR
// Nécessaire car Three.js accède à window, document et WebGL
const renderer = new THREE.WebGLRenderer({ canvas, antialias: true })
const loader = new OBJLoader()
loader.load('/models/model.obj', (obj) => scene.add(obj))
// Export GLTF pour la réalité augmentée (model-viewer)
const exporter = new GLTFExporter()
exporter.parse(scene, (gltf) => {
const blob = new Blob([gltf as ArrayBuffer], { type: 'model/gltf-binary' })
arUrl.value = URL.createObjectURL(blob)
}, { binary: true })Pattern Pinia Store
Le store panier utilise le Setup Store de Pinia avec persistance automatique via localStorage.
export const useCartStore = defineStore('cart', () => {
const items = ref<CartItem[]>([])
const total = computed(() =>
items.value.reduce((sum, i) => sum + i.price * i.quantity, 0).toFixed(2)
)
const count = computed(() =>
items.value.reduce((sum, i) => sum + i.quantity, 0)
)
function hydrate() {
if (!import.meta.client) return // Guard SSR
const saved = localStorage.getItem('aurora-cart')
if (saved) items.value = JSON.parse(saved)
}
function persist() {
localStorage.setItem('aurora-cart', JSON.stringify(items.value))
}
function addItem(product: Product) {
const existing = items.value.find(i => i.id === product.id)
existing ? existing.quantity++ : items.value.push({ ...product, quantity: 1 })
persist()
}
return { items, total, count, hydrate, addItem, decreaseItem, removeItem, clear }
})La guard import.meta.client garantit que localStorage n'est jamais accédé côté serveur.
Pattern API Routes (Nitro)
Les routes serveur suivent la convention méthode-suffixe de Nitro. Les transactions SQLite garantissent l'atomicité des opérations critiques (création commande + décrément stock).
export default defineEventHandler(async (event) => {
const body = await readBody<ConfirmOrderBody>(event)
// Transaction atomique : création commande + décrément stock
return db.transaction(() => {
const { lastInsertRowid } = db.prepare(
'INSERT INTO orders (total, delivery_type) VALUES (?, ?)'
).run(body.total, body.deliveryType)
for (const item of body.items) {
db.prepare('UPDATE products SET stock = stock - ? WHERE id = ?')
.run(item.quantity, item.id)
db.prepare(
'INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)'
).run(lastInsertRowid, item.id, item.quantity, item.price)
}
return { success: true } satisfies SuccessResponse
})()
})Le suffixe de la méthode HTTP (.get.ts, .post.ts, .put.ts) est résolu automatiquement par Nitro — aucun routeur manuel requis.
State Machine — Tunnel d'achat
La navigation du panier est modélisée comme une machine à états avec le type discriminé CheckoutStep.
type CheckoutStep = 'cart' | 'delivery' | 'checkout' | 'payment'
const step = ref<CheckoutStep>('cart')
// Navigation linéaire :
// cart → delivery → checkout → payment
// ↑ ↑ ↑ ↑
// Panier Livraison Adresse StripeLancer le projet
npm install
npm run dev # http://localhost:3000
npm run buildSite en production : aurora-home-marketing.vercel.app