docs: ticket booking system guide (#13471)
* docs: ticket booking system guide * fix vale error
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -279,7 +279,7 @@ Find all methods generated by the `MedusaService` in [the Service Factory refere
|
||||
|
||||
</Note>
|
||||
|
||||
### Export Module Definition
|
||||
### d. Export Module Definition
|
||||
|
||||
The final piece to a module is its definition, which you export in an `index.ts` file at its root directory. This definition tells Medusa the name of the module and its service.
|
||||
|
||||
@@ -303,7 +303,7 @@ You use the `Module` function to create the module's definition. It accepts two
|
||||
|
||||
You also export the module's name as `PREORDER_MODULE` so you can reference it later.
|
||||
|
||||
### Add Module to Medusa's Configurations
|
||||
### e. Add Module to Medusa's Configurations
|
||||
|
||||
Once you finish building the module, add it to Medusa's configurations to start using it.
|
||||
|
||||
@@ -322,7 +322,7 @@ module.exports = defineConfig({
|
||||
|
||||
Each object in the `modules` array has a `resolve` property, whose value is either a path to the module's directory, or an `npm` package’s name.
|
||||
|
||||
### Generate Migrations
|
||||
### f. Generate Migrations
|
||||
|
||||
Since data models represent tables in the database, you define how they're created in the database with migrations. A migration is a TypeScript class that defines database changes made by a module.
|
||||
|
||||
|
||||
@@ -36,10 +36,6 @@ Only one provider can be defined for a channel.
|
||||
</Note>
|
||||
|
||||
```ts title="medusa-config.ts"
|
||||
import { Modules } from "@medusajs/framework/utils"
|
||||
|
||||
// ...
|
||||
|
||||
module.exports = defineConfig({
|
||||
// ...
|
||||
modules: [
|
||||
|
||||
4816
www/apps/resources/app/recipes/ticket-booking/example/page.mdx
Normal file
4816
www/apps/resources/app/recipes/ticket-booking/example/page.mdx
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
250
www/apps/resources/app/recipes/ticket-booking/page.mdx
Normal file
250
www/apps/resources/app/recipes/ticket-booking/page.mdx
Normal file
@@ -0,0 +1,250 @@
|
||||
---
|
||||
products:
|
||||
- product
|
||||
- cart
|
||||
- order
|
||||
---
|
||||
|
||||
import { AcademicCapSolid, PuzzleSolid } from "@medusajs/icons";
|
||||
|
||||
export const metadata = {
|
||||
title: `Ticket Booking System Recipe`,
|
||||
};
|
||||
|
||||
# {metadata.title}
|
||||
|
||||
This recipe provides the general steps to implement a ticket booking system in your Medusa application.
|
||||
|
||||
<Note>
|
||||
|
||||
Follow the step-by-step [Ticket Booking System Example](./example/page.mdx) to learn how to implement a ticket booking system in your Medusa application.
|
||||
|
||||
</Note>
|
||||
|
||||
## Overview
|
||||
|
||||
A ticket booking system allows customers to book tickets for events, such as shows or sports games. By using a ticket booking system, you can manage shows, venues, and seat availability, among other features.
|
||||
|
||||
Medusa's [Framework](!docs!/learn/fundamentals/framework) facilitates building a ticket booking system on top of the existing commerce functionalities, such as products, pricing, inventory, carts, and orders. All of these are provided by Medusa's [Commerce Modules](../../commerce-modules/page.mdx).
|
||||
|
||||
To support ticket-booking features, you can customize the Medusa application by creating a Ticket Booking Module, linking its data models to Medusa's existing models, and building flows around the module.
|
||||
|
||||
---
|
||||
|
||||
## Create Ticket Booking Module
|
||||
|
||||
Your custom features and functionalities are implemented inside modules. The module is integrated into the Medusa application without any implications on existing functionalities.
|
||||
|
||||
The module will hold your custom data models and the service implementing ticket-booking-related features.
|
||||
|
||||
<Card
|
||||
href="!docs!/learn/fundamentals/modules"
|
||||
title="How to Create a Module"
|
||||
text="Learn how to create a module."
|
||||
icon={AcademicCapSolid}
|
||||
/>
|
||||
|
||||
### Create Custom Data Models
|
||||
|
||||
A data model represents a table in the database. You can define in your module data models to store data related to your custom features, such as shows, venues, and seats.
|
||||
|
||||
For example, you can define:
|
||||
|
||||
- A `Venue` model for the venue where the event takes place.
|
||||
- A `TicketProduct` model for a show, and a `TicketProductVariant` model for the ticket variants (for example, different seating sections).
|
||||
- A `TicketPurchase` model for a ticket purchase.
|
||||
|
||||
Then, you can link your custom data model to data models from other modules. For example, you can link:
|
||||
|
||||
- The `TicketProduct` model to the Product Module's `Product` data model, benefiting from existing features related to products and collections.
|
||||
- The `TicketProductVariant` model to the Product Module's `ProductVariant` data model, benefiting from existing features related to inventory and pricing.
|
||||
- The `TicketPurchase` model to the Order Module's `Order` data model, benefiting from existing features related to orders and payments.
|
||||
|
||||
<CardList itemsPerRow={2} items={[
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/modules#1-create-data-model",
|
||||
title: "How to Create a Data Model",
|
||||
text: "Learn how to create a data model.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/module-links",
|
||||
title: "Define Module Links",
|
||||
text: "Define links between data models.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
|
||||
### Implement Data Management Features
|
||||
|
||||
Your module’s main service holds data-management and other related features. Then, in other resources, such as an API route, you can resolve the service from the Medusa container and use its functionalities.
|
||||
|
||||
Medusa facilitates implementing data-management features using the service factory. Your module's main service can extend this service factory, and it generates data-management methods for your data models.
|
||||
|
||||
<Card
|
||||
href="!docs!/learn/fundamentals/modules/service-factory"
|
||||
title="Service Factory"
|
||||
text="Learn about the service factory and how to use it."
|
||||
icon={AcademicCapSolid}
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
## Implement Ticket Booking Business Flows
|
||||
|
||||
You can implement ticket-booking-related business logic in workflows. A workflow is a series of queries and actions, called steps, that complete a task.
|
||||
|
||||
By using workflows, you benefit from features like rollback mechanisms, error handling, and retrying failed steps. You can then execute workflows from other resources, such as an API route.
|
||||
|
||||
You can implement workflows that create venues and ticket products, complete carts with ticket products, and more. In the workflow's steps, you can resolve the Ticket Booking Module's service and use its data-management methods to manage ticket-booking-related data.
|
||||
|
||||
You can then utilize the API routes that execute these workflows in your client applications, such as your Medusa Admin customizations or your storefront.
|
||||
|
||||
<CardList itemsPerRow={2} items={[
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/workflows",
|
||||
title: "Workflows",
|
||||
text: "Learn how to create a workflow.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/api-routes",
|
||||
title: "API Routes",
|
||||
text: "Learn how to create API routes.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## Handle Ticket Products Inventory
|
||||
|
||||
By linking the `TicketProductVariant` model to the Product Module's `ProductVariant` model, you can leverage Medusa's inventory management features, implemented in the Inventory Module, to manage ticket product variants' inventory.
|
||||
|
||||
You can set up inventory items for ticket product variants based on show dates and seating sections. You can set the available quantity for each inventory item to reflect the number of seats available in that section for that show date.
|
||||
|
||||
This setup ensures that customers can only book tickets for available seats, preventing overbooking.
|
||||
|
||||
<CardList itemsPerRow={2} items={[
|
||||
{
|
||||
href: "/commerce-modules/inventory",
|
||||
title: "Inventory Module",
|
||||
text: "Learn about the Inventory Module and its features.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "/commerce-modules/product/variant-inventory",
|
||||
title: "Product Variant Inventory",
|
||||
text: "Learn how to manage product variant inventory.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## Disable Shipping on Ticket Product Variants
|
||||
|
||||
By default, Medusa product variants require shipping, which prompts the customer to provide a shipping address and choose a shipping method during checkout.
|
||||
|
||||
You can disable shipping on ticket product variants by setting the `requires_shipping` property of the product variant's inventory item to `false`.
|
||||
|
||||
Then, you can remove shipping-related steps from the checkout flow in the storefront.
|
||||
|
||||
<Card
|
||||
href="/commerce-modules/product/selling-products#configure-shipping-requirements"
|
||||
title="Configure Shipping Requirements"
|
||||
text="Learn how to configure shipping requirements for product variants."
|
||||
icon={AcademicCapSolid}
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
## Customize Admin Dashboard
|
||||
|
||||
You can extend the Medusa Admin to provide merchants with an interface to manage ticket-booking-related data, such as shows and venues. You can inject widgets into existing pages or create new pages.
|
||||
|
||||
In your customizations, you send requests to the API routes you created that execute the workflows implementing ticket-booking-related features.
|
||||
|
||||
<CardList items={[
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/admin/widgets",
|
||||
title: "Create a Widget",
|
||||
text: "Learn how to create a widget in the Medusa Admin.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/admin/ui-routes",
|
||||
title: "Create UI Route",
|
||||
text: "Learn how to create a UI route in the Medusa Admin.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## Add Custom Validation on Cart Operations
|
||||
|
||||
Medusa's workflows provide hooks that allow you to inject custom logic at specific points in the workflow execution.
|
||||
|
||||
Specifically, workflows like `addToCartWorkflow` and `completeCartWorkflow` provide a `validate` hook that you can consume to add custom validation logic.
|
||||
|
||||
For example, you can consume the `validate` hook in the `addToCartWorkflow` to check if the selected seat is available before adding a ticket product variant to the cart.
|
||||
|
||||
<Card
|
||||
href="!docs!/learn/fundamentals/workflows/workflow-hooks"
|
||||
title="Workflow Hooks"
|
||||
text="Learn how to use workflow hooks."
|
||||
icon={AcademicCapSolid}
|
||||
/>
|
||||
|
||||
---
|
||||
|
||||
## Send Order Confirmation Email with QR Code Ticket
|
||||
|
||||
When an order is placed, Medusa emits an `order.placed` event. You can listen to this event in a subscriber, which is an asynchronous function executed in the background when its associated event is emitted.
|
||||
|
||||
In the subscriber, you can send an email using the Notification Module. You can register a Notification Module Provider, such as [SendGrid](../../infrastructure-modules/notification/sendgrid/page.mdx) or [Resend](../../integrations/guides/resend/page.mdx), that sends the email.
|
||||
|
||||
You can include a QR code representing the ticket in the email, which you can generate using a library like `qrcode`.
|
||||
|
||||
You can also implement an API route that verifies the QR code at the event entrance.
|
||||
|
||||
<CardList itemsPerRow={2} items={[
|
||||
{
|
||||
href: "!docs!/learn/fundamentals/events-and-subscribers",
|
||||
title: "Events and Subscribers",
|
||||
text: "Learn how to create a subscriber.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "/infrastructure-modules/notification",
|
||||
title: "Notification Module",
|
||||
text: "Learn about available Notification Module Providers.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
|
||||
---
|
||||
|
||||
## Customize or Build Storefront
|
||||
|
||||
Customers can book tickets through your storefront. They need features like listing shows, selecting show dates and seats, and placing orders through a checkout flow that supports ticket products.
|
||||
|
||||
Medusa provides a Next.js Starter Storefront with standard commerce features including listing products, placing orders, and managing accounts. You can customize the storefront and tailor its functionalities to support ticket booking features.
|
||||
|
||||
Alternatively, you can build the storefront with your preferred tech stack.
|
||||
|
||||
<CardList items={[
|
||||
{
|
||||
href: "/nextjs-starter",
|
||||
title: "Next.js Starter Storefront",
|
||||
text: "Learn how to install and use the Next.js Starter Storefront.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
{
|
||||
href: "/storefront-development",
|
||||
title: "Storefront Guides",
|
||||
text: "Learn how to build a storefront for your Medusa application.",
|
||||
icon: AcademicCapSolid,
|
||||
},
|
||||
]} />
|
||||
@@ -196,7 +196,7 @@ export const generatedEditDates = {
|
||||
"app/commerce-modules/auth/create-actor-type/page.mdx": "2025-05-20T07:51:40.707Z",
|
||||
"app/infrastructure-modules/page.mdx": "2025-05-21T13:01:59.821Z",
|
||||
"app/infrastructure-modules/workflow-engine/redis/page.mdx": "2025-06-24T08:50:10.115Z",
|
||||
"app/infrastructure-modules/notification/sendgrid/page.mdx": "2025-05-20T07:51:40.715Z",
|
||||
"app/infrastructure-modules/notification/sendgrid/page.mdx": "2025-09-10T12:12:04.142Z",
|
||||
"app/commerce-modules/api-key/concepts/page.mdx": "2025-08-01T15:40:51.530Z",
|
||||
"app/infrastructure-modules/workflow-engine/page.mdx": "2025-04-17T08:29:00.881Z",
|
||||
"app/infrastructure-modules/cache/page.mdx": "2025-04-17T08:29:00.741Z",
|
||||
@@ -6559,7 +6559,7 @@ export const generatedEditDates = {
|
||||
"app/commerce-modules/promotion/promotion-taxes/page.mdx": "2025-06-27T15:44:46.638Z",
|
||||
"app/troubleshooting/payment/page.mdx": "2025-07-16T10:20:24.799Z",
|
||||
"app/recipes/personalized-products/example/page.mdx": "2025-07-22T08:53:58.182Z",
|
||||
"app/how-to-tutorials/tutorials/preorder/page.mdx": "2025-08-13T12:09:06.154Z",
|
||||
"app/how-to-tutorials/tutorials/preorder/page.mdx": "2025-09-09T14:02:55.378Z",
|
||||
"references/js_sdk/admin/Order/methods/js_sdk.admin.Order.archive/page.mdx": "2025-07-24T08:20:57.709Z",
|
||||
"references/js_sdk/admin/Order/methods/js_sdk.admin.Order.complete/page.mdx": "2025-07-24T08:20:57.714Z",
|
||||
"app/commerce-modules/cart/cart-totals/page.mdx": "2025-07-31T15:18:13.978Z",
|
||||
@@ -6572,5 +6572,10 @@ export const generatedEditDates = {
|
||||
"app/commerce-modules/order/draft-orders/page.mdx": "2025-08-26T09:21:49.780Z",
|
||||
"app/troubleshooting/scheduled-job-not-running/page.mdx": "2025-08-29T11:32:54.117Z",
|
||||
"app/troubleshooting/pnpm/page.mdx": "2025-08-29T12:21:24.692Z",
|
||||
"app/how-to-tutorials/tutorials/product-feed/page.mdx": "2025-09-01T13:19:59.335Z"
|
||||
"app/how-to-tutorials/tutorials/product-feed/page.mdx": "2025-09-01T13:19:59.335Z",
|
||||
"app/recipes/ticket-booking/examples/page.mdx": "2025-09-10T14:11:55.063Z",
|
||||
"app/recipes/ticket-booking/examples/storefront/page.mdx": "2025-09-10T14:14:44.005Z",
|
||||
"app/recipes/ticket-booking/example/page.mdx": "2025-09-10T15:13:15.604Z",
|
||||
"app/recipes/ticket-booking/example/storefront/page.mdx": "2025-09-10T15:26:04.084Z",
|
||||
"app/recipes/ticket-booking/page.mdx": "2025-09-11T06:53:21.071Z"
|
||||
}
|
||||
@@ -1115,6 +1115,18 @@ export const filesMap = [
|
||||
"filePath": "/www/apps/resources/app/recipes/subscriptions/page.mdx",
|
||||
"pathname": "/recipes/subscriptions"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/recipes/ticket-booking/example/page.mdx",
|
||||
"pathname": "/recipes/ticket-booking/example"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/recipes/ticket-booking/example/storefront/page.mdx",
|
||||
"pathname": "/recipes/ticket-booking/example/storefront"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/recipes/ticket-booking/page.mdx",
|
||||
"pathname": "/recipes/ticket-booking"
|
||||
},
|
||||
{
|
||||
"filePath": "/www/apps/resources/app/references-overview/page.mdx",
|
||||
"pathname": "/references-overview"
|
||||
|
||||
@@ -11794,6 +11794,14 @@ const generatedgeneratedCommerceModulesSidebarSidebar = {
|
||||
"path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/product-reviews",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "ref",
|
||||
"title": "Implement Ticket Booking",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
|
||||
@@ -140,6 +140,48 @@ const generatedgeneratedRecipesSidebarSidebar = {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/personalized-products",
|
||||
"title": "Personalized Products",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/personalized-products/example",
|
||||
"title": "Example",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/ticket-booking",
|
||||
"title": "Ticket Booking",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/ticket-booking/example",
|
||||
"title": "Example",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/ticket-booking/example/storefront",
|
||||
"title": "Storefront Customizations",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
@@ -172,23 +214,6 @@ const generatedgeneratedRecipesSidebarSidebar = {
|
||||
"title": "OMS",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/personalized-products",
|
||||
"title": "Personalized Products",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/recipes/personalized-products/example",
|
||||
"title": "Example",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
|
||||
@@ -859,6 +859,14 @@ const generatedgeneratedToolsSidebarSidebar = {
|
||||
"title": "Saved Payment Methods",
|
||||
"path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/saved-payment-methods",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "ref",
|
||||
"title": "Ticket Booking Storefront",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example/storefront",
|
||||
"children": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -97,6 +97,35 @@ export const recipesSidebar = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/personalized-products",
|
||||
title: "Personalized Products",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/personalized-products/example",
|
||||
title: "Example",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/ticket-booking",
|
||||
title: "Ticket Booking",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/ticket-booking/example",
|
||||
title: "Example",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/ticket-booking/example/storefront",
|
||||
title: "Storefront Customizations",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/ecommerce",
|
||||
@@ -117,18 +146,6 @@ export const recipesSidebar = [
|
||||
path: "/recipes/oms",
|
||||
title: "OMS",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/personalized-products",
|
||||
title: "Personalized Products",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/personalized-products/example",
|
||||
title: "Example",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/recipes/pos",
|
||||
|
||||
@@ -22,5 +22,9 @@ export const nextjs = [
|
||||
{
|
||||
"title": "Saved Payment Methods",
|
||||
"path": "https://docs.medusajs.com/resources/how-to-tutorials/tutorials/saved-payment-methods"
|
||||
},
|
||||
{
|
||||
"title": "Ticket Booking Storefront",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example/storefront"
|
||||
}
|
||||
]
|
||||
@@ -111,6 +111,10 @@ export const product = [
|
||||
"title": "Implement Personalized Products",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/personalized-products/example"
|
||||
},
|
||||
{
|
||||
"title": "Implement Ticket Booking",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example"
|
||||
},
|
||||
{
|
||||
"title": "Implement Express Checkout with Medusa",
|
||||
"path": "https://docs.medusajs.com/resources/storefront-development/guides/express-checkout"
|
||||
|
||||
@@ -151,6 +151,10 @@ export const server = [
|
||||
"title": "Personalized Products",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/personalized-products/example"
|
||||
},
|
||||
{
|
||||
"title": "Example",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example"
|
||||
},
|
||||
{
|
||||
"title": "Use Analytics Module",
|
||||
"path": "https://docs.medusajs.com/resources/references/analytics/service"
|
||||
|
||||
@@ -102,5 +102,13 @@ export const tutorial = [
|
||||
{
|
||||
"title": "Personalized Products",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/personalized-products/example"
|
||||
},
|
||||
{
|
||||
"title": "Example",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example"
|
||||
},
|
||||
{
|
||||
"title": "Storefront Customizations",
|
||||
"path": "https://docs.medusajs.com/resources/recipes/ticket-booking/example/storefront"
|
||||
}
|
||||
]
|
||||
Reference in New Issue
Block a user