From 09a949092c59856962e4a7d132bc5a5e76fe5e55 Mon Sep 17 00:00:00 2001 From: ertopogo Date: Sun, 18 Jan 2026 20:32:59 +0100 Subject: Initial commit: Medusa Backend + storefront + config --- INSTALLATION.md | 86 +++++++++++++++++++++++++++++++++ POSTGRES_DIAG.md | 81 +++++++++++++++++++++++++++++++ apache-vhost.conf | 26 ++++++++++ backend/Dockerfile | 21 ++++++++ backend/index.js | 45 ++++++++++++++++++ backend/medusa-config.js | 103 ++++++++++++++++++++++++++++++++++++++++ backend/package.json | 59 +++++++++++++++++++++++ backend/tsconfig.json | 25 ++++++++++ docker-compose.yml | 38 +++++++++++++++ env- | 35 ++++++++++++++ env-example | 35 ++++++++++++++ storefront/Dockerfile | 35 ++++++++++++++ storefront/lib/medusa-client.js | 6 +++ storefront/next.config.js | 10 ++++ storefront/package.json | 31 ++++++++++++ storefront/pages/_app.js | 17 +++++++ storefront/pages/index.js | 26 ++++++++++ working.otl | 13 +++++ 18 files changed, 692 insertions(+) create mode 100644 INSTALLATION.md create mode 100644 POSTGRES_DIAG.md create mode 100644 apache-vhost.conf create mode 100644 backend/Dockerfile create mode 100644 backend/index.js create mode 100644 backend/medusa-config.js create mode 100644 backend/package.json create mode 100644 backend/tsconfig.json create mode 100644 docker-compose.yml create mode 100644 env- create mode 100644 env-example create mode 100644 storefront/Dockerfile create mode 100644 storefront/lib/medusa-client.js create mode 100644 storefront/next.config.js create mode 100644 storefront/package.json create mode 100644 storefront/pages/_app.js create mode 100644 storefront/pages/index.js create mode 100644 working.otl diff --git a/INSTALLATION.md b/INSTALLATION.md new file mode 100644 index 0000000..69bcd4c --- /dev/null +++ b/INSTALLATION.md @@ -0,0 +1,86 @@ +# Guide d'Installation Complet - Lucien-sens-bon + +Ce guide détaille comment installer votre boutique MedusaJS (Backend) + Next.js (Frontend) sur votre serveur "huitral" avec Docker et Apache. + +## 1. Pré-requis + +Assurez-vous d'avoir : +- **Docker** et **Docker Compose** installés. +- Une base de données **PostgreSQL** accessible (version 12+ recommandée). +- **Apache** installé sur la machine hôte. + +## 2. Configuration Initiale + +1. **Variables d'environnement** : + Copiez le fichier d'exemple pour créer votre fichier de configuration réel : + ```bash + cp env-example .env + ``` + +2. **Éditez le fichier `.env`** : + Modifiez les valeurs, notamment la connexion à la base de données (`DATABASE_URL`). + + *Note : Si votre Postgres est sur la machine hôte (hors Docker), utilisez `host.docker.internal` comme hôte dans l'URL de connexion, ou l'IP locale du serveur.* + +## 3. Installation et Démarrage + +Lancez les conteneurs (cela va construire les images Backend et Storefront) : + +```bash +docker-compose up -d --build +``` + +Cela va démarrer 3 conteneurs : +- `medusa-backend` (API) sur le port 9000 +- `medusa-storefront` (Site Web) sur le port 8000 +- `medusa-redis` (Cache) sur le port 6379 + +## 4. Initialisation de la Base de Données + +Une fois les conteneurs démarrés, vous devez initialiser la base de données Medusa (créer les tables) et créer un utilisateur administrateur. + +1. **Lancer les migrations et le "seed" (données de démo)** : + ```bash + docker exec -it medusa-backend npm run seed + ``` + *(Si cela échoue, assurez-vous que la base de données est vide ou que la connexion est correcte).* + +2. **Créer un utilisateur Admin** : + ```bash + docker exec -it medusa-backend medusa user -e admin@lucien.com -p supersecret + ``` + *(Remplacez l'email et le mot de passe par les vôtres).* + +## 5. Configuration Apache (Reverse Proxy) + +Pour rendre le site accessible depuis le web (port 80/443), configurez Apache sur votre machine hôte. + +1. **Copiez la configuration** : + Utilisez le contenu du fichier `apache-vhost.conf` fourni dans ce projet et ajoutez-le à votre configuration Apache (généralement dans `/etc/apache2/sites-available/lucien.conf`). + +2. **Activez les modules Proxy** (si ce n'est pas déjà fait) : + ```bash + sudo a2enmod proxy + sudo a2enmod proxy_http + ``` + +3. **Activez le site et redémarrez Apache** : + ```bash + sudo a2ensite lucien.conf + sudo service apache2 restart + ``` + +## 6. Vérification + +- **Storefront** : Accédez à `http://lucien-sens-bon.com` (ou votre domaine). Vous devriez voir la page d'accueil. +- **Admin** : Accédez à `http://api.lucien-sens-bon.com/app` (le dashboard admin est servi par le backend). Connectez-vous avec l'utilisateur créé à l'étape 4. + +## 7. Paiements Crypto + +Pour activer les paiements Crypto, nous vous conseillons d'installer un plugin comme `medusa-payment-coinbase` ou d'utiliser une intégration Stripe Crypto si disponible. + +L'ajout d'un plugin se fait en 2 étapes : +1. Ajouter le package dans `backend/package.json`. +2. Ajouter la configuration dans `backend/medusa-config.js`. +3. Reconstruire le conteneur (`docker-compose up -d --build`). + diff --git a/POSTGRES_DIAG.md b/POSTGRES_DIAG.md new file mode 100644 index 0000000..8a07377 --- /dev/null +++ b/POSTGRES_DIAG.md @@ -0,0 +1,81 @@ +# Aide-Mémoire Diagnostic PostgreSQL + +Ce fichier regroupe les commandes essentielles pour diagnostiquer les problèmes de connexion, de droits et de performance sur PostgreSQL. + +## 1. Connexion au serveur (Ligne de commande) + +Se connecter en tant que super-administrateur (localement) : +```bash +sudo -u postgres psql +``` + +Tester une connexion distante (depuis une autre machine) : +```bash +# -h = hôte, -U = utilisateur, -d = base de données, -W = demander le mot de passe +psql -h 192.168.99.35 -U lucien -d medusa_db -W +``` + +## 2. Commandes d'Inspection (dans psql `postgres=#`) + +### Utilisateurs et Droits +| Commande | Description | +| :--- | :--- | +| `\du` | Liste tous les utilisateurs et leurs rôles (Superuser, Create DB, etc.). | +| `\du+` | Même chose avec plus de détails (description). | +| `SELECT current_user;` | Affiche l'utilisateur avec lequel vous êtes connecté. | + +### Bases de données +| Commande | Description | +| :--- | :--- | +| `\l` | Liste toutes les bases de données et leurs propriétaires. | +| `\c ma_base` | Se connecter à la base `ma_base`. | +| `\dt` | Liste les tables de la base courante. | + +### Configuration et Fichiers +| Commande | Description | +| :--- | :--- | +| `SHOW config_file;` | Affiche le chemin du fichier `postgresql.conf`. | +| `SHOW hba_file;` | Affiche le chemin du fichier `pg_hba.conf` (règles de connexion). | +| `SHOW listen_addresses;` | Affiche les IPs écoutées (doit être `*` pour accès distant). | +| `SHOW port;` | Affiche le port (défaut 5432). | +| `SHOW password_encryption;` | Affiche l'algorithme de hachage (souvent `scram-sha-256` ou `md5`). | + +## 3. Diagnostic des Connexions Actives + +Voir qui est connecté et ce qu'ils font : +```sql +SELECT pid, usename, client_addr, state, query +FROM pg_stat_activity +WHERE state != 'idle'; +``` + +Voir les connexions bloquées : +```sql +SELECT pid, usename, query +FROM pg_stat_activity +WHERE wait_event_type = 'Lock'; +``` + +## 4. Gestion des Mots de Passe + +Si vous avez un doute sur un mot de passe ou une méthode de chiffrement (md5 vs scram), la meilleure solution est de le redéfinir : + +```sql +-- Réinitialiser le mot de passe +ALTER USER nom_utilisateur WITH PASSWORD 'nouveau_mot_de_passe'; +``` + +## 5. Problèmes Courants `pg_hba.conf` + +Si vous avez l'erreur `no pg_hba.conf entry for host...`, vérifiez le fichier `pg_hba.conf`. + +1. Ouvrir le fichier (chemin obtenu via `SHOW hba_file;`). +2. Vérifier la présence d'une ligne comme : + ```text + # TYPE DATABASE USER ADDRESS METHOD + host all all 0.0.0.0/0 scram-sha-256 + ``` +3. **IMPORTANT** : Après toute modification, recharger la config : + ```bash + sudo systemctl reload postgresql + ``` diff --git a/apache-vhost.conf b/apache-vhost.conf new file mode 100644 index 0000000..66bb310 --- /dev/null +++ b/apache-vhost.conf @@ -0,0 +1,26 @@ + + ServerName lucien-sens-bon.com + ServerAlias www.lucien-sens-bon.com + + ProxyPreserveHost On + ProxyPass / http://localhost:8000/ + ProxyPassReverse / http://localhost:8000/ + + ErrorLog ${APACHE_LOG_DIR}/storefront-error.log + CustomLog ${APACHE_LOG_DIR}/storefront-access.log combined + + + + ServerName api.lucien-sens-bon.com + + ProxyPreserveHost On + ProxyPass / http://localhost:9000/ + ProxyPassReverse / http://localhost:9000/ + + ErrorLog ${APACHE_LOG_DIR}/api-error.log + CustomLog ${APACHE_LOG_DIR}/api-access.log combined + + +# Note : Pour activer SSL (https), utilisez Certbot : +# sudo certbot --apache -d lucien-sens-bon.com -d api.lucien-sens-bon.com + diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..6775ba5 --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,21 @@ +FROM node:18-alpine + +WORKDIR /app/medusa + +COPY package.json . +COPY yarn.lock* ./ +COPY package-lock.json* ./ + +RUN npm install + +COPY . . + +# Build the project (if using TypeScript) +RUN npm run build + +# Expose port +EXPOSE 9000 + +# Start command +CMD ["npm", "run", "start"] + diff --git a/backend/index.js b/backend/index.js new file mode 100644 index 0000000..ad245ba --- /dev/null +++ b/backend/index.js @@ -0,0 +1,45 @@ +const express = require("express"); +const { GracefulShutdownServer } = require("medusa-core-utils"); + +const loaders = require("@medusajs/medusa/dist/loaders/index").default; + +(async () => { + async function start() { + const app = express(); + const directory = process.cwd(); + + try { + const { container, dbConnection } = await loaders({ + directory, + expressApp: app, + }); + + const configModule = container.resolve("configModule"); + const port = process.env.PORT ?? configModule.projectConfig.port ?? 9000; + + const server = GracefulShutdownServer.create( + app.listen(port, (err) => { + if (err) { + return; + } + console.log(`Server is ready on port: ${port}`); + }) + ); + + // Handle graceful shutdown + const shutdown = async () => { + await server.shutdown(); + await dbConnection.close(); + }; + + process.on("SIGTERM", shutdown); + process.on("SIGINT", shutdown); + } catch (err) { + console.error("Error starting server", err); + process.exit(1); + } + } + + await start(); +})(); + diff --git a/backend/medusa-config.js b/backend/medusa-config.js new file mode 100644 index 0000000..739a553 --- /dev/null +++ b/backend/medusa-config.js @@ -0,0 +1,103 @@ +const dotenv = require("dotenv"); + +let ENV_FILE_NAME = ""; +switch (process.env.NODE_ENV) { + case "production": + ENV_FILE_NAME = ".env.production"; + break; + case "staging": + ENV_FILE_NAME = ".env.staging"; + break; + case "test": + ENV_FILE_NAME = ".env.test"; + break; + case "development": + default: + ENV_FILE_NAME = ".env"; + break; +} + +try { + dotenv.config({ path: process.cwd() + "/" + ENV_FILE_NAME }); +} catch (e) {} + +// CORS when consuming Medusa from admin +const ADMIN_CORS = + process.env.ADMIN_CORS || "http://localhost:7000,http://localhost:7001"; + +// CORS to avoid issues when consuming Medusa from a client +const STORE_CORS = process.env.STORE_CORS || "http://localhost:8000"; + +const DATABASE_URL = + process.env.DATABASE_URL || "postgres://localhost/medusa-store"; + +const REDIS_URL = process.env.REDIS_URL || "redis://localhost:6379"; + +const plugins = [ + `medusa-fulfillment-manual`, + `medusa-payment-manual`, + { + resolve: `@medusajs/file-local`, + options: { + upload_dir: "uploads", + }, + }, + { + resolve: "@medusajs/admin", + /** @type {import('@medusajs/admin').PluginOptions} */ + options: { + autoRebuild: true, + develop: { + open: false, + }, + }, + }, + // Example for Stripe (uncomment and configure in .env) + // { + // resolve: `medusa-payment-stripe`, + // options: { + // api_key: process.env.STRIPE_API_KEY, + // webhook_secret: process.env.STRIPE_WEBHOOK_SECRET, + // }, + // }, +]; + +const modules = { + /* + * Enable the Redis event bus to sync events + */ + eventBus: { + resolve: "@medusajs/event-bus-redis", + options: { + redisUrl: REDIS_URL + } + }, + /* + * Enable Redis cache + */ + cacheService: { + resolve: "@medusajs/cache-redis", + options: { + redisUrl: REDIS_URL + } + }, +}; + +/** @type {import('@medusajs/medusa').ConfigModule["projectConfig"]} */ +const projectConfig = { + jwtSecret: process.env.JWT_SECRET, + cookieSecret: process.env.COOKIE_SECRET, + store_cors: STORE_CORS, + database_url: DATABASE_URL, + admin_cors: ADMIN_CORS, + // Uncomment the following lines to enable REDIS + redis_url: REDIS_URL +}; + +/** @type {import('@medusajs/medusa').ConfigModule} */ +module.exports = { + projectConfig, + plugins, + modules, +}; + diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..5a4c902 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,59 @@ +{ + "name": "medusa-backend", + "version": "0.0.1", + "description": "A Medusa e-commerce backend", + "author": "Lucien-sens-bon", + "license": "MIT", + "keywords": [ + "sqlite", + "postgres", + "typescript", + "ecommerce", + "headless", + "medusa" + ], + "scripts": { + "clean": "cross-env ./node_modules/.bin/rimraf dist", + "build": "cross-env ./node_modules/.bin/rimraf dist && tsc -p tsconfig.json", + "start": "cross-env npm run build && medusa start", + "start:custom": "cross-env npm run build && node --preserve-symlinks index.js", + "dev": "cross-env npm run build && medusa develop", + "seed": "medusa seed -f ./data/seed.json", + "install:cli": "npm install -g @medusajs/medusa-cli" + }, + "dependencies": { + "@medusajs/medusa": "^1.20.0", + "@medusajs/medusa-cli": "^1.3.21", + "@medusajs/cache-inmemory": "^1.8.9", + "@medusajs/cache-redis": "^1.8.9", + "@medusajs/event-bus-local": "^1.9.7", + "@medusajs/event-bus-redis": "^1.8.10", + "@medusajs/file-local": "^1.0.2", + "@medusajs/admin": "^7.1.14", + "body-parser": "^1.19.0", + "cors": "^2.8.5", + "dotenv": "16.3.1", + "express": "^4.17.1", + "medusa-interfaces": "^1.3.7", + "medusa-payment-manual": "^1.0.24", + "medusa-payment-stripe": "^6.0.7", + "typeorm": "^0.3.16", + "typescript": "^4.5.2" + }, + "devDependencies": { + "@types/express": "^4.17.13", + "@types/jest": "^27.4.0", + "@types/node": "^17.0.8", + "babel-preset-medusa-package": "^1.1.19", + "cross-env": "^7.0.3", + "eslint": "^6.8.0", + "jest": "^27.3.1", + "rimraf": "^3.0.2", + "ts-jest": "^27.0.7", + "ts-loader": "^9.2.6" + }, + "engines": { + "node": ">=16" + } +} + diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..725f746 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true, + "skipLibCheck": true + }, + "include": [ + "src/**/*" + ], + "exclude": [ + "node_modules", + "dist", + "test" + ] +} + diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..775365f --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3.8' + +services: + backend: + build: ./backend + container_name: medusa-backend + environment: + - DATABASE_URL=${DATABASE_URL} + - REDIS_URL=redis://redis:6379 + - JWT_SECRET=${JWT_SECRET} + - COOKIE_SECRET=${COOKIE_SECRET} + - NODE_ENV=production + - ADMIN_CORS=${ADMIN_CORS} + - STORE_CORS=${STORE_CORS} + depends_on: + - redis + ports: + - "9000:9000" + volumes: + - ./backend/uploads:/app/medusa/uploads + restart: always + + storefront: + build: ./storefront + container_name: medusa-storefront + environment: + - NEXT_PUBLIC_MEDUSA_BACKEND_URL=${NEXT_PUBLIC_MEDUSA_BACKEND_URL} + ports: + - "8000:8000" + restart: always + + redis: + image: redis:alpine + container_name: medusa-redis + ports: + - "6379:6379" + restart: always + diff --git a/env- b/env- new file mode 100644 index 0000000..bed7b21 --- /dev/null +++ b/env- @@ -0,0 +1,35 @@ +# -------------------------------------------------------- +# CONFIGURATION DE LA BASE DE DONNEES +# Remplacez , , par vos vraies infos +# Si Postgres est sur la machine hôte et pas dans Docker, utilisez l'IP locale ou host.docker.internal +# -------------------------------------------------------- +DATABASE_URL=postgres://postgres:password@host.docker.internal:5432/medusa_db + +# -------------------------------------------------------- +# CLES DE SECURITE +# Générez des clés aléatoires complexes pour la production +# -------------------------------------------------------- +JWT_SECRET=supersecret +COOKIE_SECRET=supersecret + +# -------------------------------------------------------- +# CONFIGURATION DES URLS +# Pour la production, mettez vos vrais domaines (ex: https://api.monsite.com) +# -------------------------------------------------------- + +# URL du Backend (API) accessible par le navigateur +NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://localhost:9000 + +# CORS Admin : Quels domaines peuvent accéder à l'admin ? +ADMIN_CORS=http://localhost:7000,http://localhost:7001 + +# CORS Store : Quels domaines (le frontend) peuvent accéder à l'API ? +# En production, ce sera https://monsite.com +STORE_CORS=http://localhost:8000 + +# -------------------------------------------------------- +# PAIEMENTS (Optionnel) +# -------------------------------------------------------- +STRIPE_API_KEY= +STRIPE_WEBHOOK_SECRET= + diff --git a/env-example b/env-example new file mode 100644 index 0000000..bed7b21 --- /dev/null +++ b/env-example @@ -0,0 +1,35 @@ +# -------------------------------------------------------- +# CONFIGURATION DE LA BASE DE DONNEES +# Remplacez , , par vos vraies infos +# Si Postgres est sur la machine hôte et pas dans Docker, utilisez l'IP locale ou host.docker.internal +# -------------------------------------------------------- +DATABASE_URL=postgres://postgres:password@host.docker.internal:5432/medusa_db + +# -------------------------------------------------------- +# CLES DE SECURITE +# Générez des clés aléatoires complexes pour la production +# -------------------------------------------------------- +JWT_SECRET=supersecret +COOKIE_SECRET=supersecret + +# -------------------------------------------------------- +# CONFIGURATION DES URLS +# Pour la production, mettez vos vrais domaines (ex: https://api.monsite.com) +# -------------------------------------------------------- + +# URL du Backend (API) accessible par le navigateur +NEXT_PUBLIC_MEDUSA_BACKEND_URL=http://localhost:9000 + +# CORS Admin : Quels domaines peuvent accéder à l'admin ? +ADMIN_CORS=http://localhost:7000,http://localhost:7001 + +# CORS Store : Quels domaines (le frontend) peuvent accéder à l'API ? +# En production, ce sera https://monsite.com +STORE_CORS=http://localhost:8000 + +# -------------------------------------------------------- +# PAIEMENTS (Optionnel) +# -------------------------------------------------------- +STRIPE_API_KEY= +STRIPE_WEBHOOK_SECRET= + diff --git a/storefront/Dockerfile b/storefront/Dockerfile new file mode 100644 index 0000000..b6c1da8 --- /dev/null +++ b/storefront/Dockerfile @@ -0,0 +1,35 @@ +# Install dependencies only when needed +FROM node:18-alpine AS deps +WORKDIR /app +COPY package.json yarn.lock* package-lock.json* ./ +RUN npm ci + +# Rebuild the source code only when needed +FROM node:18-alpine AS builder +WORKDIR /app +COPY --from=deps /app/node_modules ./node_modules +COPY . . +# Disable telemetry during build +ENV NEXT_TELEMETRY_DISABLED 1 +RUN npm run build + +# Production image, copy all the files and run next +FROM node:18-alpine AS runner +WORKDIR /app +ENV NODE_ENV production +ENV NEXT_TELEMETRY_DISABLED 1 + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +COPY --from=builder /app/public ./public +COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +EXPOSE 8000 +ENV PORT 8000 + +CMD ["node", "server.js"] + diff --git a/storefront/lib/medusa-client.js b/storefront/lib/medusa-client.js new file mode 100644 index 0000000..0b78f76 --- /dev/null +++ b/storefront/lib/medusa-client.js @@ -0,0 +1,6 @@ +import Medusa from "@medusajs/medusa-js" + +const BACKEND_URL = process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL || "http://localhost:9000" + +export const medusaClient = new Medusa({ baseUrl: BACKEND_URL, maxRetries: 3 }) + diff --git a/storefront/next.config.js b/storefront/next.config.js new file mode 100644 index 0000000..255e46c --- /dev/null +++ b/storefront/next.config.js @@ -0,0 +1,10 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, + images: { + domains: ["localhost", "medusa-public-images.s3.eu-west-1.amazonaws.com"], + }, +} + +module.exports = nextConfig + diff --git a/storefront/package.json b/storefront/package.json new file mode 100644 index 0000000..fefa31c --- /dev/null +++ b/storefront/package.json @@ -0,0 +1,31 @@ +{ + "name": "medusa-storefront", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "next dev -p 8000", + "build": "next build", + "start": "next start -p 8000", + "lint": "next lint" + }, + "dependencies": { + "@medusajs/medusa": "^1.20.0", + "@medusajs/medusa-js": "^6.1.7", + "@tanstack/react-query": "4.22.0", + "medusa-react": "^9.0.15", + "next": "13.4.12", + "react": "18.2.0", + "react-dom": "18.2.0", + "clsx": "^2.0.0", + "lucide-react": "^0.263.1" + }, + "devDependencies": { + "autoprefixer": "^10.4.14", + "postcss": "^8.4.27", + "tailwindcss": "^3.3.3", + "typescript": "5.1.6", + "@types/react": "18.2.18", + "@types/node": "20.4.9" + } +} + diff --git a/storefront/pages/_app.js b/storefront/pages/_app.js new file mode 100644 index 0000000..1424c52 --- /dev/null +++ b/storefront/pages/_app.js @@ -0,0 +1,17 @@ +import { MedusaProvider } from "medusa-react" +import { QueryClient } from "@tanstack/react-query" +import { medusaClient } from "../lib/medusa-client" + +const queryClient = new QueryClient() + +export default function App({ Component, pageProps }) { + return ( + + + + ) +} + diff --git a/storefront/pages/index.js b/storefront/pages/index.js new file mode 100644 index 0000000..fa4a592 --- /dev/null +++ b/storefront/pages/index.js @@ -0,0 +1,26 @@ +import { useProducts } from "medusa-react" + +export default function Home() { + const { products, isLoading } = useProducts() + + return ( +
+

Bienvenue sur la boutique Lucien-sens-bon

+ {isLoading && Chargement des produits...} + +
+ {products && products.map((product) => ( +
+

{product.title}

+

{product.description}

+
+ ))} +
+ + {!isLoading && !products?.length && ( +

Aucun produit trouvé. Connectez-vous à l'admin pour en ajouter !

+ )} +
+ ) +} + diff --git a/working.otl b/working.otl new file mode 100644 index 0000000..34ed087 --- /dev/null +++ b/working.otl @@ -0,0 +1,13 @@ +application web avec technologie à définir +application pour vendre des produits +application web qui sera hosted par apache sur un docker dédié sur huitral. + +est-ce qu'il existe un code open-source pour créer un site de ventes qui soit bien noté, +que je pourrais utiliser ? il faut que les payments puissent être intégrés facilement, si c'est possible, +pouvoir offrir le payment en cryptomonnaie. + +que me conseilles tu ? + + + + -- cgit v1.2.3