# medusa-plugin-product-description

AI-powered product & category description generator plugin for [MedusaJS v2](https://medusajs.com/).

This plugin uses AI (via [OpenRouter](https://openrouter.ai/)) to generate SEO-optimized descriptions for **products and categories** in Spanish. It adds widgets on the product and category detail pages, plus a dedicated admin page for batch operations and cache management.

## Features

- **Product detail widget**: "Generar Descripcion con IA" button directly on the product edit page
- **Category detail widget**: "Generar Descripcion de Categoria con IA" button directly on the category edit page
- **Admin page "IA Descripciones"**: individual generation for products and categories, batch generation of ALL products/categories, and cache revalidation
- AI generation via **OpenRouter** (OpenAI-compatible API, supports any model: Google Gemini, GPT, Claude, etc.)
- Configurable prompts via environment variables
- Automatic date stamp: *"Descripcion actualizada el DD/MM/AAAA"*
- Server-side cache revalidation via `STOREFRONT_URL`
- Batch operations with progress bar and cost warning
- Zero hardcoded URLs — works on any Medusa installation

## Prerequisites

- MedusaJS v2.13.0 or later
- Node.js v20 or later
- An [OpenRouter](https://openrouter.ai/) API key (free tier available)

## Installation

```bash
npm install medusa-plugin-product-description
```

## Configuration

### 1. Environment Variables

Add the following to your Medusa project's `.env` file:

```env
OPENROUTER_API_KEY=sk-or-v1-your-key-here
OPENROUTER_MODEL=google/gemma-3-12b-it:free
OPENROUTER_SITE_URL=https://your-store.com
OPENROUTER_APP_NAME=Your Store Admin
STOREFRONT_URL=https://your-storefront.com
AI_DESCRIPTION_PROMPT=Genera una descripcion atractiva, natural y optimizada para SEO sobre el producto "{productTitle}". ...
AI_CATEGORY_PROMPT=Escribe una descripcion breve, natural y optimizada para SEO en Markdown sobre la categoria **{categoryName}**. ...
```

| Variable | Required | Default | Description |
|---|---|---|---|
| `OPENROUTER_API_KEY` | Yes | — | OpenRouter API key (sign up at [openrouter.ai](https://openrouter.ai/)) |
| `OPENROUTER_MODEL` | No | `google/gemma-3-12b-it:free` | Model to use. [Browse models](https://openrouter.ai/models) |
| `OPENROUTER_SITE_URL` | No | — | Your site URL (sent as `HTTP-Referer` header) |
| `OPENROUTER_APP_NAME` | No | `Medusa Admin` | Your app name (sent as `X-Title` header) |
| `STOREFRONT_URL` | No | — | Your storefront base URL for cache revalidation (e.g. `https://tustore.com`) |
| `AI_DESCRIPTION_PROMPT` | No | Default prompt (see below) | Prompt template for products. Use `{productTitle}` as placeholder |
| `AI_CATEGORY_PROMPT` | No | Default prompt (see below) | Prompt template for categories. Use `{categoryName}` as placeholder |

**Default product prompt:**

```
Genera una descripcion atractiva, natural y optimizada para SEO sobre el producto "{productTitle}".
Debe parecer redactada por un humano y no mostrar rastros de IA.
Incluye iconos emoji de forma moderada y utiliza formato en Markdown.

La descripcion debe estar lista para publicarse directamente, sin frases introductorias, anotaciones ni indicaciones.
90-140 palabras.
```

**Default category prompt:**

```
Escribe una descripcion breve, natural y optimizada para SEO en Markdown sobre la categoria **{categoryName}**.
Incluye 2-4 emojis pertinentes (sin abusar).

Requisitos:
- 90-140 palabras.
- Tono cercano, profesional y claro.
- Nada de instrucciones meta ni disculpas; texto final listo para publicar.
```

### 2. Medusa Configuration

In your `medusa-config.ts`, register the plugin:

```ts
import { defineConfig } from "@medusajs/framework/config"

export default defineConfig({
  plugins: [
    {
      resolve: "medusa-plugin-product-description",
      options: {},
    },
  ],
})
```

## Usage

### Widgets (recommended)

The plugin injects widgets directly into the Medusa admin:

- **Product detail page** (`/app/products/:id`): A "Generar Descripcion con IA" section appears below the product details. Generate, edit, save, and revalidate — all without leaving the page.
- **Category detail page** (`/app/categories/:id`): Same widget for categories, with sibling category context for better AI results.

### Admin Page: IA Descripciones

Navigate to **IA Descripciones** in the sidebar for advanced operations:

**Individual generation:**
- Enter a product or category ID, load it, generate a description, edit and save.

**Batch generation:**
- Generate descriptions for **ALL products** or **ALL categories** in one go.
- A progress bar shows real-time status.
- ⚠️ **Warning**: This calls the OpenRouter API for every entity. Use with caution — it may consume significant API credits.

**Cache management:**
- Revalidate products cache, categories cache, or both at once.
- Requires `STOREFRONT_URL` environment variable pointing to your storefront.

### Next.js Revalidation Endpoint

If you're using a Next.js storefront, this plugin calls `{STOREFRONT_URL}/api/revalidate?tags=...` to revalidate the ISR cache. Add this endpoint:

```ts
// frontend/src/app/api/revalidate/route.ts
import { revalidateTag } from "next/cache"
import { NextRequest, NextResponse } from "next/server"

export async function GET(request: NextRequest) {
  const tag = request.nextUrl.searchParams.get("tags") || "products"
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, tag })
}
```

## API Endpoints

### `POST /admin/ai-description`

Generate a product description.

**Request:**
```json
{ "productId": "prod_01JABC...", "productTitle": "Paracetamol 650mg" }
```

**Response:**
```json
{ "description": "## Paracetamol 650mg\n\nAlivia el dolor y la fiebre con..." }
```

### `POST /admin/ai-category-description`

Generate a category description. Optionally include sibling category names for context.

**Request:**
```json
{
  "categoryId": "pcat_01JABC...",
  "categoryName": "Analgesicos",
  "relatedCategories": ["Antiinflamatorios", "Antigripales"]
}
```

**Response:**
```json
{ "description": "## Analgesicos\n\nEncuentra los mejores analgesicos..." }
```

### `POST /admin/revalidate-cache`

Trigger cache revalidation on the storefront. Requires `STOREFRONT_URL` environment variable.

**Request:**
```json
{ "tags": "products" }
```

**Response:**
```json
{ "revalidated": true, "tags": "products" }
```

## Development

```bash
# Install dependencies
npm install

# Build the plugin
npm run build

# Watch mode (for local plugin development)
npm run dev
```

### Local Testing with a Medusa Project

```bash
# From your plugin directory
npm run dev

# In your Medusa project directory:
npx medusa plugin:add ../path-to/medusa-plugin-product-description
```

## Publishing to NPM

```bash
npx medusa plugin:build
npm publish
```

To publish an update:

```bash
npm version patch   # or minor / major
npx medusa plugin:build
npm publish
```

## License

MIT
