import React from "react"
import { LearningPathType } from "../providers/LearningPath"
import Link from "@docusaurus/Link"
const paths: LearningPathType[] = [
{
name: "simple-quickstart",
label: "Start Selling in 3 Steps",
description: "Create and deploy a full-fledged ecommerce store.",
steps: [
{
title: "Create a Next.js Starter Template",
description:
"Create a Next.js Starter Template and connect it to your Medusa backend.",
path: "/starters/nextjs-medusa-starter",
},
{
title: "Deploy the backend",
path: "/deployments/server/deploying-on-railway",
descriptionJSX: (
<>
Deploy your backend to Railway. You can alternatively check out{" "}
other deployment guides
>
),
},
{
title: "Deploy the storefront",
description: "Deploy your storefront to your preferred hosting.",
path: "/deployments/storefront",
},
],
finish: {
type: "rating",
step: {
title: "Congratulations on building your store!",
description: "Please rate your experience using this recipe.",
eventName: "rating_path_simple-quickstart",
},
},
},
{
name: "marketplace",
label: "Build a marketplace",
description:
"Customize the backend and handle events to build a marketplace.",
steps: [
{
title: "Extend entities",
descriptionJSX: (
<>
Extend entities, such as User or Product{" "}
entities, to associate them with the Store entity.
>
),
path: "/development/entities/extend-entity",
},
{
title: "Access logged-in user",
description:
"Create a middleware that registers the logged-in user in the dependency container.",
path: "/development/api-routes/example-logged-in-user",
},
{
title: "Extend services",
descriptionJSX: (
<>
Extend services, such as ProductService to customize
data management functionalities
>
),
path: "/development/services/extend-service",
},
{
title: "Handle events",
descriptionJSX: (
<>
Listen to events like order.placed and handle them with
subscribers
>
),
path: "/development/events/create-subscriber",
},
{
title: "Add Payment Provider",
path: "/plugins/payment",
descriptionJSX: (
<>
Add a payment provider to your Medusa backend. You can choose to
install a plugin or{" "}
create your own provider
.
>
),
},
{
title: "Customize Admin",
path: "/admin/widgets",
descriptionJSX: (
<>
As you add marketplace features to your store, you'll most
likely need to customize the admin to provide an interface to manage
these features.
You can extend the admin plugin to add widgets,{" "}
UI routes, or{" "}
setting pages.
>
),
},
{
title: "Implement Role-Based Access Control",
path: "/modules/users/backend/rbac",
description:
"In your marketplace, you may need to implement role-based access control (RBAC) within stores. This will restrict some users' permissions to specified functionalities or API Routes.",
},
{
title: "Create a storefront",
path: "/starters/nextjs-medusa-starter",
descriptionJSX: (
<>
Build a storefront either using the Next.js Starter Template or{" "}
from scratch.
>
),
},
{
title: "Deploy the backend",
path: "/deployments/server/deploying-on-railway",
descriptionJSX: (
<>
Deploy your backend to Railway. You can alternatively check out{" "}
other deployment guides
>
),
},
],
finish: {
type: "rating",
step: {
title: "Congratulations on building your marketplace!",
description: "Please rate your experience using this recipe.",
eventName: "rating_path_marketplace",
},
},
},
{
name: "subscriptions",
label: "Build Subscription-based Purchases",
description:
"Customize the backend and handle events to implement subscriptions",
steps: [
{
title: "Extend entities",
path: "/development/entities/extend-entity",
descriptionJSX: (
<>
Extend entities, such as the Order entity, to associate
them with the Store entity. You can also{" "}
Create a custom entity
.
>
),
},
{
title: "Handle events",
descriptionJSX: (
<>
Create a subscriber that listens to the order.placed{" "}
event, or other{" "}
events, and
handles creating the subscription in Medusa.
>
),
path: "/development/events/create-subscriber",
},
{
title: "Create a Scheduled Job",
description:
"Create a scheduled job that checks daily for subscriptions that needs renewal.",
path: "/development/scheduled-jobs/create",
},
{
title: "Customize Admin",
path: "/admin/widgets",
descriptionJSX: (
<>
As you add subscription features to your store, you may need to
customize the admin to provide an interface to manage these
features.
You can extend the admin plugin to add widgets,{" "}
UI routes, or{" "}
setting pages.
>
),
},
{
title: "Create a storefront",
path: "/starters/nextjs-medusa-starter",
descriptionJSX: (
<>
Build a storefront either using the Next.js Starter Template or{" "}
from scratch.
>
),
},
{
title: "Deploy the backend",
path: "/deployments/server/deploying-on-railway",
descriptionJSX: (
<>
Deploy your backend to Railway. You can alternatively check out{" "}
other deployment guides
>
),
},
],
finish: {
type: "rating",
step: {
title: "Congratulations on implementing subscription-based purchases!",
description: "Please rate your experience using this recipe.",
eventName: "rating_path_subscriptions",
},
},
},
{
name: "b2b",
label: "Build a B2B store",
description:
"Utilize Medusa's features and customization capabilities to build a B2B store.",
steps: [
{
title: "Create a B2B Sales Channel",
path: "/user-guide/sales-channels/manage",
descriptionJSX: (
<>
You can create a B2B sales channel that will include only your
wholesale products.
You can either use the Medusa admin, or the{" "}
Admin REST APIs
.
>
),
},
{
title: "Create a Publishable API Key",
path: "/user-guide/settings/publishable-api-keys",
descriptionJSX: (
<>
Publishable API keys can be associated with one or more sales
channels. You can then use the publishable API key in your
storefront or client.
You can either use the Medusa admin, or the{" "}
Admin REST APIs
.
>
),
},
{
title: "Add Wholesale Products",
path: "/user-guide/products/manage",
descriptionJSX: (
<>
You can add your wholesale products and make them only available in
the B2B sales channel.
You can use the Medusa admin to add the products. Other alternatives
are:
product.updated event using a{" "}
Subscriber{" "}
and execute the workflow whenever the event is triggered.
>
),
},
{
title: "Create Webhook Listeners",
path: "/development/api-routes/create",
descriptionJSX: (
<>
You can provide webhook listeners that your external systems call
when their data is updated. This lets you synchronize data between
your systems.
User entity to add the relation between it and the new{" "}
Role entity. You can also extend other entities that
are associated with your custom one, such as the Store{" "}
entity.
>
),
},
{
title: "Create Guard Middleware",
path: "/development/api-routes/add-middleware",
description:
"To ensure that users who have the privilege can access an API Route, you must create a middleware that guards admin routes. This middleware will run on all authenticated admin requests to ensure that only allowed users can access an API Route.",
},
{
title: "Create Services",
path: "/development/services/create-service",
descriptionJSX: (
<>
For every entity you create, such as the Role and{" "}
Permission entities, you must create a service that
provides create, read, update, and delete (CRUD) functionalities at
the very least.
User entity,
you may need to{" "}
extend its core service
{" "}
UserService as well to perform custom functionalities
related to your implementation.
>
),
},
{
title: "Create API Routes",
path: "/development/api-routes/create",
descriptionJSX: (
<>
To manage the roles and permissions, you’ll need to create custom
API Routes, typically for Create, Read, Update, and Delete (CRUD)
operations.
package.json in preparation for publishing.
>
),
},
{
title: "Optionally test locally",
path: "/development/plugins/create#test-your-plugin",
description:
"If necessary, you can test your plugin in a separate local Medusa backend. It's recommended, however, to do your plugin testing within the plugin project.",
},
{
title: "Publish plugin",
path: "/development/plugins/publish",
description: "Publish your plugin on NPM.",
},
],
finish: {
type: "rating",
step: {
title: "Congratulations on creating your plugin!",
description: "Please rate your experience using this recipe.",
eventName: "rating_path_plugin",
},
},
},
]
// get a shallow copy
export const getLearningPaths = () => [...paths]
export const getLearningPath = (
pathName: string
): LearningPathType | undefined => paths.find((path) => path.name === pathName)