ДокументацияРуководство РазработчикаРецепты Быстрой Кастомизации

Рецепты кастомизации и разработка новых функций

Это руководство предназначено для разработчиков, желающих расширить функционал, локализовать опции товаров или создать собственные визуальные блоки.

Рецепт 1: Управление и перевод опций товаров и цветовых образцов (`color`)

Строгое правило для ключа цвета (Color Swatches)
В панели Medusa опция цвета обязана называться строго color (или Color). Фронтенд Next.js использует этот ключ для поиска HEX-кодов и создания интерактивных образцов и визуальных фильтров.

Процесс локализации названий опций через Strapi:

  • Для остальных опций (размер, материал, бренд) название может быть любым.
  • Локализованные переводы названий опций динамически настраиваются в панели Strapi CMS.
  • Фронтенд Next.js запрашивает перевод из Strapi в соответствии с локалью пользователя, сохраняя ключ фильтрации как color.
Пример получения локализованных названий опций из Strapi на фронтенде
typescript
// store/src/lib/strapi-client/get-option-translations.ts
export async function getOptionTranslation(optionKey: string, locale: string = "fa") {
const res = await fetch(
`${process.env.NEXT_PUBLIC_STRAPI_URL}/api/option-translations?filters[key][$eq]=${optionKey}&locale=${locale}`,
{ headers: { Authorization: `Bearer ${process.env.STRAPI_API_TOKEN_FOR_FRONT}` } }
)
const json = await res.json()
return json.data?.[0]?.translated_name || optionKey
}

Рецепт 2: Добавление нового Workflow и REST API эндпоинта в Medusa v2

В Medusa v2 бизнес-логика выстраивается в виде Шагов (Steps) и Рабочих процессов (Workflows):

store-admin/src/workflows/daily-deals.ts
typescript
import { createWorkflow, createStep, StepResponse, WorkflowResponse } from "@medusajs/framework/workflows-sdk";
const fetchDealsStep = createStep("fetch-deals-step", async () => {
const deals = [{ id: "deal_1", title: "Специальное предложение дня", discount: "25%" }];
return new StepResponse(deals);
});
export const getDailyDealsWorkflow = createWorkflow("get-daily-deals", function () {
const deals = fetchDealsStep();
return new WorkflowResponse(deals);
});
store-admin/src/api/store/daily-deals/route.ts
typescript
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http";
import { getDailyDealsWorkflow } from "../../../workflows/daily-deals";
export async function GET(req: MedusaRequest, res: MedusaResponse) {
const { result } = await getDailyDealsWorkflow(req.scope).run();
res.json({ deals: result });
}

Рецепт 3: Создание нового блока для главной страницы

Блоки главной страницы находятся в store/src/modules/home/components/. Каждый блок состоит из трех частей: типизации в homepage.ts, схемы компонента в Strapi и папки React-компонента.

Реальная структура проекта
Существующие блоки, такие как FeaturesBlock, BlogPostsBlock, ProductShowcase и ProductSplitView, имеют собственные папки и распознаются в BlockRenderer по значению __component, возвращаемому Strapi.

Пример: Добавление блока «Обратный отсчет» (Countdown)

  1. Определение типа TypeScript — В файле store/src/lib/data/homepage.ts добавьте интерфейс нового блока и включите его в основной union-тип:
store/src/lib/data/homepage.ts
typescript
export interface CountdownBlock {
__component: "ui.countdown-block"
id: number
title?: string
target_date: string
}
// Добавление в union type
export type HomepageBlock =
| ProductSplitViewBlock
| ProductShowcaseBlock
| FeaturesBlock
| BlogPostsBlock
| CategoryCollectionBlock
| CountdownBlock // <-- добавлено сюда
  1. Создание папки и компонента React — Создайте папку CountdownBlock в store/src/modules/home/components/:
store/src/modules/home/components/CountdownBlock/index.tsx
tsx
import React from "react"
import type { CountdownBlock as CountdownBlockType } from "@lib/data/homepage"
interface CountdownBlockProps {
block: CountdownBlockType
}
export default function CountdownBlock({ block }: CountdownBlockProps) {
return (
<section className="py-16 text-center">
<h2 className="text-xl font-bold mb-4">{block.title}</h2>
<p className="text-gray-500">{block.target_date}</p>
</section>
)
}
  1. Регистрация в BlockRenderer — Откройте store/src/modules/home/components/BlockRenderer/index.tsx и добавьте новую ветку switch:
store/src/modules/home/components/BlockRenderer/index.tsx
tsx
import CountdownBlock from "../CountdownBlock"
// Внутри switch(block.__component) в BlockRenderer:
case "ui.countdown-block":
BlockContent = <CountdownBlock block={block} />
break
  1. Создание схемы компонента в Strapi — Создайте новый JSON-файл в папке website-admin/src/components/ui/:
website-admin/src/components/ui/countdown-block.json
json
{
"collectionName": "components_ui_countdown_blocks",
"info": {
"displayName": "Countdown Block",
"icon": "clock",
"description": "A countdown timer block for the homepage"
},
"options": {},
"attributes": {
"title": { "type": "string" },
"target_date": { "type": "datetime", "required": true }
}
}
Финальный шаг
После перезапуска Strapi откройте панель управления Homepage > Dynamic Zone. Новый «Countdown Block» появится в списке доступных компонентов.

Рецепт 4: Подключение нового платежного провайдера (Payment Provider)

Для добавления нового платежного шлюза создайте сервис, реализующий AbstractPaymentProvider в директории store-admin/src/modules/payment/, и зарегистрируйте его в medusa-config.ts в секции providers платежного модуля.