docs: add routing page (#9550)
- Add a new homepage to `book` project for the routing page - Move all main doc pages to be under `/v2/learn` (and added redirects + fixed links across docs) - Other: add admin components to resources dropdown + fixes to search on mobile. Closes DX-955 Preview: https://docs-v2-git-docs-router-page-medusajs.vercel.app/v2
This commit is contained in:
1 parent
7a47f5211d
commit
0a37675f0e
223 files changed
+2549
-696
No files matched your search
@@ -0,0 +1,379 @@
|
||||
"use client"
|
||||
|
||||
import { Link, VerticalCodeTab, VerticalCodeTabs } from "docs-ui"
|
||||
import { useState } from "react"
|
||||
|
||||
type Tab = VerticalCodeTab & {
|
||||
textSection: {
|
||||
content: string
|
||||
link: {
|
||||
title: string
|
||||
link: string
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const HomepageCodeTabs = () => {
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState(0)
|
||||
|
||||
const tabs: Tab[] = [
|
||||
{
|
||||
title: "Create API Route",
|
||||
textSection: {
|
||||
content:
|
||||
"Expose custom features with REST API routes, then consume them from your client applications.",
|
||||
link: {
|
||||
title: "API Routes",
|
||||
link: "/learn/basics/api-routes",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `export async function GET(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const query = req.scope.resolve("query")
|
||||
|
||||
const { data } = await query.graph({
|
||||
entity: "company",
|
||||
fields: ["id", "name"],
|
||||
filters: { name: "ACME" },
|
||||
})
|
||||
|
||||
res.json({
|
||||
companies: data
|
||||
})
|
||||
}`,
|
||||
highlights: [
|
||||
["1", "GET", "Create a GET endpoint."],
|
||||
[
|
||||
"5",
|
||||
`query`,
|
||||
"Query utility to retrieve data from a graph of\nall data models and their relations.",
|
||||
],
|
||||
["8", `"company"`, "Retrieve records of the `company` data model"],
|
||||
["13", "res.json", "Return a JSON response"],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Build Workflows",
|
||||
textSection: {
|
||||
content:
|
||||
"Build flows as a series of steps, with retry mechanisms and tracking of each steps' status.",
|
||||
link: {
|
||||
title: "Workflows",
|
||||
link: "/learn/basics/workflows",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `const handleDeliveryWorkflow = createWorkflow(
|
||||
"handle-delivery",
|
||||
function (input: WorkflowInput) {
|
||||
notifyRestaurantStep(input.delivery_id);
|
||||
|
||||
const order = createOrderStep(input.delivery_id);
|
||||
|
||||
createFulfillmentStep(order);
|
||||
|
||||
awaitDeliveryStep();
|
||||
|
||||
return new WorkflowResponse("Delivery completed");
|
||||
}
|
||||
)`,
|
||||
highlights: [
|
||||
[
|
||||
"1",
|
||||
"createWorkflow",
|
||||
"Use the Workflows SDK to build a flow of a series of steps.",
|
||||
],
|
||||
["4", "notifyRestaurantStep", "Run steps in the worklfow"],
|
||||
[
|
||||
"10",
|
||||
"awaitDeliveryStep",
|
||||
"Wait for background actions to finish execution\nbefore performing some steps.",
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Add a Data Model",
|
||||
textSection: {
|
||||
content:
|
||||
"Create data models that represent tables in the database using Medusa's Data Model Language.",
|
||||
link: {
|
||||
title: "DML",
|
||||
link: "/learn/basics/modules#1-create-data-model",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `const DigitalProduct = model.define("digital_product", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
medias: model.hasMany(() => DigitalProductMedia, {
|
||||
mappedBy: "digitalProduct"
|
||||
})
|
||||
})
|
||||
.cascades({
|
||||
delete: ["medias"]
|
||||
})`,
|
||||
highlights: [
|
||||
[
|
||||
"1",
|
||||
"model",
|
||||
"Use Medusa's Data Model Language to\nrepresent custom tables in the database.",
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"hasMany",
|
||||
"Create relations between models of the same module.",
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Build a Custom Module",
|
||||
textSection: {
|
||||
content:
|
||||
"Build custom modules with commerce or architectural features and use them in API routes or workflows.",
|
||||
link: {
|
||||
title: "Modules",
|
||||
link: "/learn/basics/modules",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `class DigitalProductModuleService extends MedusaService({
|
||||
DigitalProduct,
|
||||
}) {
|
||||
async authorizeLicense() {
|
||||
console.log("License authorized!")
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse
|
||||
) {
|
||||
const digitalProductModuleService = req.scope.resolve(
|
||||
"digitalProductModuleService"
|
||||
)
|
||||
|
||||
await digitalProductModuleService.authorizeLicense()
|
||||
|
||||
res.json({ success: true })
|
||||
}`,
|
||||
highlights: [
|
||||
[
|
||||
"1",
|
||||
"DigitalProductModuleService",
|
||||
"Create a service that accesses\nthe database to manage data models.",
|
||||
],
|
||||
[
|
||||
"1",
|
||||
"MedusaService",
|
||||
"Generate data-management methods\nfor your data models automatically.",
|
||||
],
|
||||
[
|
||||
"13",
|
||||
"digitalProductModuleService",
|
||||
"Resolve the database from the Medusa container\nin routes and other resources.",
|
||||
],
|
||||
["17", "authorizeLicense", "Use the service's custom methods."],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Link Data Models",
|
||||
textSection: {
|
||||
content:
|
||||
"Add custom properties to Medusa's data models using module links to build custom use cases.",
|
||||
link: {
|
||||
title: "Module Links",
|
||||
link: "/learn/advanced-development/module-links",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `const DigitalProduct = model.define("digital_product", {
|
||||
id: model.id().primaryKey(),
|
||||
name: model.text(),
|
||||
})
|
||||
|
||||
export default defineLink(
|
||||
DigitalProductModule.linkable.digitalProduct,
|
||||
ProductModule.linkable.productVariant
|
||||
)`,
|
||||
highlights: [
|
||||
[
|
||||
"6",
|
||||
"defineLink",
|
||||
"Create a link between data models of different modules.",
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Subscribe to Events",
|
||||
textSection: {
|
||||
content:
|
||||
"Handle events emitted by the Medusa application to perform custom actions.",
|
||||
link: {
|
||||
title: "Subscribers",
|
||||
link: "/learn/basics/events-and-subscribers",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "ts",
|
||||
source: `async function orderPlaced({
|
||||
container,
|
||||
}: SubscriberArgs) {
|
||||
const notificaitonModuleService = container.resolve(
|
||||
Modules.NOTIFICATION
|
||||
)
|
||||
|
||||
await notificaitonModuleService.createNotifications({
|
||||
to: "customer@gmail.com",
|
||||
channel: "email",
|
||||
template: "order-placed"
|
||||
})
|
||||
}
|
||||
|
||||
export const config: SubscriberConfig = {
|
||||
event: "order.placed",
|
||||
}`,
|
||||
highlights: [
|
||||
[
|
||||
"1",
|
||||
"orderPlaced",
|
||||
"Define a subscriber that's\nexecuted when an event is emitted.",
|
||||
],
|
||||
[
|
||||
"4",
|
||||
"notificaitonModuleService",
|
||||
"Resolve a module's main service\nto use its methods.",
|
||||
],
|
||||
["8", "createNotification", "Send an email to a customer."],
|
||||
[
|
||||
"16",
|
||||
`"order.placed"`,
|
||||
"Execute the subscriber when an order is placed.",
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Customize Admin",
|
||||
textSection: {
|
||||
content:
|
||||
"Inject widgets into predefined zones in the Medusa Admin, or add new pages.",
|
||||
link: {
|
||||
title: "Admin Customizations",
|
||||
link: "/learn/basics/admin-customizations",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "tsx",
|
||||
source: `const ProductBrandWidget = () => {
|
||||
const [brand, setBrand] = useState({
|
||||
name: "Acme"
|
||||
})
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Heading level="h2">Brand</Heading>
|
||||
{brand && <span>Name: {brand.name}</span>}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export const config = defineWidgetConfig({
|
||||
zone: "product.details.before",
|
||||
})`,
|
||||
highlights: [
|
||||
[
|
||||
"1",
|
||||
"ProductBrandWidget",
|
||||
"Create admin widgets as React components.",
|
||||
],
|
||||
[
|
||||
"7",
|
||||
"Container",
|
||||
"Use Medusa's UI components in your customizations.",
|
||||
],
|
||||
[
|
||||
"15",
|
||||
`"product.details.before"`,
|
||||
"Show the widget on the product details page.",
|
||||
],
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Integrate Systems",
|
||||
textSection: {
|
||||
content:
|
||||
"Build workflows around multiple systems to add more powerful features to Medusa.",
|
||||
link: {
|
||||
title: "Integrate Systems",
|
||||
link: "/learn/customization/integrate-systems",
|
||||
},
|
||||
},
|
||||
code: {
|
||||
lang: "tsx",
|
||||
source: `const syncBrandsFromSystemWorkflow = createWorkflow(
|
||||
"sync-brands-from-system",
|
||||
() => {
|
||||
const toCreate = retrieveBrandsFromSystemStep()
|
||||
|
||||
const created = createBrandsInMedusaStep({
|
||||
brands: toCreate
|
||||
})
|
||||
|
||||
return new WorkflowResponse({
|
||||
created,
|
||||
})
|
||||
}
|
||||
)`,
|
||||
highlights: [
|
||||
["1", "createWorkflow", "Integrate systems using workflows."],
|
||||
[
|
||||
"4",
|
||||
"retrieveBrandsFromSystemStep",
|
||||
"Retrieve data from an external system.",
|
||||
],
|
||||
["6", "createBrandsInMedusaStep", "Sync data to Medusa."],
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="row-span-2 pt-[56px] hidden lg:flex flex-col gap-1">
|
||||
<VerticalCodeTabs
|
||||
selectedTabIndex={selectedTabIndex}
|
||||
setSelectedTabIndex={setSelectedTabIndex}
|
||||
tabs={tabs}
|
||||
className="h-[443px]"
|
||||
/>
|
||||
<div className="flex gap-[6px] items-center mx-0.5">
|
||||
<span className="text-medusa-fg-subtle text-small-plus">
|
||||
{tabs[selectedTabIndex].textSection.content}
|
||||
</span>
|
||||
<span className="text-medusa-fg-subtle text-small">·</span>
|
||||
<Link
|
||||
href={tabs[selectedTabIndex].textSection.link.link}
|
||||
className="text-compact-small-plus"
|
||||
withIcon
|
||||
>
|
||||
<span>{tabs[selectedTabIndex].textSection.link.title}</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageCodeTabs
|
||||
@@ -0,0 +1,24 @@
|
||||
import clsx from "clsx"
|
||||
import Feedback from "../../Feedback"
|
||||
import EditButton from "../../EditButton"
|
||||
|
||||
const HomepageFooter = () => {
|
||||
return (
|
||||
<div className="py-4 w-full">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex flex-col lg:flex-row gap-2 justify-between lg:items-center",
|
||||
"xl:mx-auto xl:max-w-[1136px] w-full px-1 sm:px-4 xl:px-0"
|
||||
)}
|
||||
>
|
||||
<Feedback
|
||||
showDottedSeparator={false}
|
||||
question="Was this page helpful?"
|
||||
/>
|
||||
<EditButton />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageFooter
|
||||
@@ -0,0 +1,95 @@
|
||||
import clsx from "clsx"
|
||||
import { Link } from "docs-ui"
|
||||
|
||||
const HomepageLinksSection = () => {
|
||||
const sections: SectionProps[] = [
|
||||
{
|
||||
title: "Customize Medusa Application",
|
||||
links: [
|
||||
{
|
||||
href: "/learn",
|
||||
text: "Create your first application",
|
||||
},
|
||||
{
|
||||
href: "/learn/customization",
|
||||
text: "Build a Module",
|
||||
},
|
||||
{
|
||||
href: "https://docs.medusajs.com/v2/resources/integrations",
|
||||
text: "Browse third-party integrations",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Admin Development",
|
||||
links: [
|
||||
{
|
||||
href: "/learn/basics/admin-customizations",
|
||||
text: "Build a UI Widget",
|
||||
},
|
||||
{
|
||||
href: "/learn/advanced-development/admin/ui-routes",
|
||||
text: "Add a UI Route",
|
||||
},
|
||||
{
|
||||
href: "https://docs.medusajs.com/ui",
|
||||
text: "Browse the UI component library",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Storefront Development",
|
||||
links: [
|
||||
{
|
||||
href: "https://docs.medusajs.com/v2/resources/nextjs-starter",
|
||||
text: "Explore our storefront starter",
|
||||
},
|
||||
{
|
||||
href: "https://docs.medusajs.com/v2/resources/storefront-development",
|
||||
text: "Build a custom storefront",
|
||||
},
|
||||
{
|
||||
href: "https://docs.medusajs.com/ui",
|
||||
text: "Browse the UI component library",
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"hidden lg:block py-4 w-full",
|
||||
"border-y border-medusa-border-base xl:mx-auto"
|
||||
)}
|
||||
>
|
||||
<div className="flex gap-4 flex-wrap xl:mx-auto xl:max-w-[1136px] w-full px-4 xl:px-0">
|
||||
{sections.map((section, index) => (
|
||||
<Section {...section} key={index} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type SectionProps = {
|
||||
title: string
|
||||
links: {
|
||||
text: string
|
||||
href: string
|
||||
}[]
|
||||
}
|
||||
|
||||
const Section = ({ title, links }: SectionProps) => {
|
||||
return (
|
||||
<div className="flex flex-col gap-0.5 flex-1">
|
||||
<h3 className="text-h3 text-medusa-fg-base">{title}</h3>
|
||||
{links.map((link, index) => (
|
||||
<Link key={index} className="text-compact-small-plus" href={link.href}>
|
||||
{link.text}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageLinksSection
|
||||
@@ -0,0 +1,203 @@
|
||||
import clsx from "clsx"
|
||||
import { Card, CardProps, IconHeadline, PuzzleColoredIcon } from "docs-ui"
|
||||
import { basePathUrl } from "../../../utils/base-path-url"
|
||||
|
||||
const HomepageModulesSection = () => {
|
||||
const sections: SectionProps[] = [
|
||||
{
|
||||
title: "Cart & Purchase",
|
||||
text: "Checkout, Total calculations, and more",
|
||||
modules: [
|
||||
{
|
||||
title: "Cart",
|
||||
text: "Add to cart, checkout, and totals.",
|
||||
href: "/resources/commerce-modules/cart",
|
||||
image: basePathUrl("/images/cart-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Payment",
|
||||
text: "Process any payment type.",
|
||||
href: "/resources/commerce-modules/payment",
|
||||
image: basePathUrl("/images/payment-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Customer",
|
||||
text: "Customer and group management.",
|
||||
href: "/resources/commerce-modules/customer",
|
||||
image: basePathUrl("/images/customer-icon.png"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Merchandising",
|
||||
text: "Products, pricing, and promotions.",
|
||||
modules: [
|
||||
{
|
||||
title: "Pricing",
|
||||
text: "Configurable pricing engine",
|
||||
href: "/resources/commerce-modules/pricing",
|
||||
image: basePathUrl("/images/pricing-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Promotion",
|
||||
text: "Discounts and promotions",
|
||||
href: "/resources/commerce-modules/promotion",
|
||||
image: basePathUrl("/images/promotion-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Product",
|
||||
text: "Variants, categories, and bulk edits",
|
||||
href: "/resources/commerce-modules/product",
|
||||
image: basePathUrl("/images/product-icon.png"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Fulfillment",
|
||||
text: "OMS, fulfilment, and inventory.",
|
||||
modules: [
|
||||
{
|
||||
title: "Order",
|
||||
text: "Omnichannel order management",
|
||||
href: "/resources/commerce-modules/order",
|
||||
image: basePathUrl("/images/order-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Inventory",
|
||||
text: "Multi-warehouse and reservations",
|
||||
href: "/resources/commerce-modules/inventory",
|
||||
image: basePathUrl("/images/inventory-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Fulfillment",
|
||||
text: "Order fulfillment and shipping",
|
||||
href: "/resources/commerce-modules/fulfillment",
|
||||
image: basePathUrl("/images/fulfillment-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Stock Location",
|
||||
text: "Locations of stock-kept items",
|
||||
href: "/resources/commerce-modules/stock-location",
|
||||
image: basePathUrl("/images/stock-location-icon.png"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Regions & Channels",
|
||||
text: "Multi-region and omnichannel support.",
|
||||
modules: [
|
||||
{
|
||||
title: "Region",
|
||||
text: "Cross-border commerce",
|
||||
href: "/resources/commerce-modules/region",
|
||||
image: basePathUrl("/images/region-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Sales Channel",
|
||||
text: "Omnichannel sales",
|
||||
href: "/resources/commerce-modules/sales-channel",
|
||||
image: basePathUrl("/images/sales-channel-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Tax",
|
||||
text: "Granular tax control",
|
||||
href: "/resources/commerce-modules/stock-location",
|
||||
image: basePathUrl("/images/tax-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Currency",
|
||||
text: "Multi-currency support",
|
||||
href: "/resources/commerce-modules/currency",
|
||||
image: basePathUrl("/images/currency-icon.png"),
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "User Access",
|
||||
text: "API keys and authentication.",
|
||||
modules: [
|
||||
{
|
||||
title: "API Keys",
|
||||
text: "Store and admin access",
|
||||
href: "/resources/commerce-modules/api-key",
|
||||
image: basePathUrl("/images/api-key-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "User Module",
|
||||
text: "Admin user management",
|
||||
href: "/resources/commerce-modules/user",
|
||||
image: basePathUrl("/images/user-icon.png"),
|
||||
},
|
||||
{
|
||||
title: "Auth",
|
||||
text: "Integrate authentication methods",
|
||||
href: "/resources/commerce-modules/auth",
|
||||
image: basePathUrl("/images/auth-icon.png"),
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="py-4 w-full border-y border-medusa-border-base">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex flex-col",
|
||||
"gap-[40px] xs:gap-4",
|
||||
"xl:mx-auto xl:max-w-[1136px] w-full px-1 sm:px-4 xl:px-0"
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-0.5 lg:max-w-[560px]">
|
||||
<IconHeadline
|
||||
title="Browse Commerce Modules"
|
||||
icon={<PuzzleColoredIcon />}
|
||||
/>
|
||||
<h2 className="text-medusa-fg-base text-h1">
|
||||
All commerce features are provided as extendable modules in Medusa.
|
||||
</h2>
|
||||
<span className="text-medusa-fg-subtle text-small-plus">
|
||||
Click on any of the commerce modules below to learn more about their
|
||||
commerce features, and how to extend and use them for your custom
|
||||
use-case.
|
||||
</span>
|
||||
</div>
|
||||
{sections.map((section, index) => (
|
||||
<Section {...section} key={index} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type SectionProps = {
|
||||
title: string
|
||||
text: string
|
||||
modules: Omit<CardProps, "type">[]
|
||||
}
|
||||
|
||||
const Section = ({ title, text, modules }: SectionProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx("flex flex-col lg:flex-row", "gap-1.5 xs:gap-2 lg:gap-4")}
|
||||
>
|
||||
<div className="flex flex-col gap-0.5 text-medusa-fg-base w-full lg:w-1/3">
|
||||
<h3 className="text-small-plus">{title}</h3>
|
||||
<span className="text-h2">{text}</span>
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
"grid xs:grid-cols-2 xs:grid-rows-2",
|
||||
"grid-cols-1 grid-rows-1",
|
||||
"lg:gap-x-4 lg:gap-y-0.75 gap-0.75",
|
||||
"w-full lg:w-2/3"
|
||||
)}
|
||||
>
|
||||
{modules.map((card, index) => (
|
||||
<Card {...card} type="default" key={index} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageModulesSection
|
||||
@@ -0,0 +1,90 @@
|
||||
import { TriangleRightMini } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import {
|
||||
CalendarRefreshIcon,
|
||||
Card,
|
||||
CardProps,
|
||||
ChefHatIcon,
|
||||
IconHeadline,
|
||||
ImageBinaryIcon,
|
||||
Link,
|
||||
ScrollTextIcon,
|
||||
ShopIcon,
|
||||
} from "docs-ui"
|
||||
|
||||
const HomepageRecipesSection = () => {
|
||||
const cards: CardProps[] = [
|
||||
{
|
||||
type: "large",
|
||||
title: "Marketplace",
|
||||
text: "Build a marketplace with multiple vendors",
|
||||
href: "https://docs.medusajs.com/v2/resources/recipes/marketplace/examples/vendors",
|
||||
icon: ShopIcon,
|
||||
},
|
||||
{
|
||||
type: "large",
|
||||
title: "Subscriptions",
|
||||
text: "Implement a subscription-based commerce store.",
|
||||
href: "https://docs.medusajs.com/v2/resources/recipes/subscriptions/examples/standard",
|
||||
icon: CalendarRefreshIcon,
|
||||
},
|
||||
{
|
||||
type: "large",
|
||||
title: "Restaurant-Delivery",
|
||||
text: "Build a restaurant marketplace inspired by UberEats, with real-time delivery handling",
|
||||
href: "https://docs.medusajs.com/v2/resources/recipes/marketplace/examples/restaurant-delivery",
|
||||
icon: ChefHatIcon,
|
||||
},
|
||||
{
|
||||
type: "large",
|
||||
title: "Digital Products",
|
||||
text: "Sell digital products with custom fulfillment.",
|
||||
href: "https://docs.medusajs.com/v2/resources/recipes/digital-products/examples/standard",
|
||||
icon: ImageBinaryIcon,
|
||||
},
|
||||
]
|
||||
return (
|
||||
<div className={clsx("py-4 w-full")}>
|
||||
<div
|
||||
className={clsx(
|
||||
"flex flex-col lg:flex-row",
|
||||
"gap-2 lg:gap-4",
|
||||
"xl:mx-auto xl:max-w-[1136px] w-full px-1 sm:px-4 xl:px-0"
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-1 w-full lg:w-1/3 xl:max-w-[336px]">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<IconHeadline title="Recipes" icon={<ScrollTextIcon />} />
|
||||
<h2 className="text-h1 text-medusa-fg-base">
|
||||
Medusa’s framework supports any business use case.
|
||||
</h2>
|
||||
<span className="text-medusa-fg-subtle text-small-plus">
|
||||
These recipes show how you to build a use case by customizing and
|
||||
extending existing data models and features, or creating new ones.
|
||||
</span>
|
||||
</div>
|
||||
<Link
|
||||
href={"https://docs.medusajs.com/v2/resources/recipes"}
|
||||
className="flex gap-0.25 items-center text-compact-small-plus"
|
||||
withIcon
|
||||
>
|
||||
<span>View All Recipes</span>
|
||||
</Link>
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
"grid xs:grid-cols-2 xs:grid-rows-2 lg:gap-x-4 lg:gap-y-1.5",
|
||||
"xs:gap-x-1.5 xs:gap-y-2 grid-cols-1 gap-1.5",
|
||||
"w-full lg:w-2/3"
|
||||
)}
|
||||
>
|
||||
{cards.map((card, index) => (
|
||||
<Card {...card} key={index} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageRecipesSection
|
||||
@@ -0,0 +1,76 @@
|
||||
/* eslint-disable @next/next/no-img-element */
|
||||
import clsx from "clsx"
|
||||
import { BookIcon, Card, IconHeadline, WindowPaintbrushIcon } from "docs-ui"
|
||||
import { basePathUrl } from "../../../utils/base-path-url"
|
||||
import HomepageCodeTabs from "../CodeTabs"
|
||||
|
||||
const HomepageTopSection = () => {
|
||||
return (
|
||||
<div className="w-full relative">
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute h-full",
|
||||
"left-0 top-0 w-full z-0 lg:hidden bg-contain bg-right-bottom bg-no-repeat"
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: `url(${basePathUrl(
|
||||
"/images/get-started-card-md.png"
|
||||
)})`,
|
||||
}}
|
||||
/>
|
||||
<div
|
||||
className={clsx(
|
||||
"absolute h-full lg:h-[calc(50%-32px)] border-b border-medusa-border-base",
|
||||
"left-0 top-0 w-full z-1 bg-cover bg-repeat",
|
||||
"bg-bg-stripes dark:bg-bg-stripes-dark"
|
||||
)}
|
||||
/>
|
||||
<div
|
||||
className={clsx(
|
||||
"w-fit mx-auto lg:grid lg:grid-cols-2 lg:grid-rows-2",
|
||||
"xl:grid-cols-[336px_752px] lg:grid-cols-[25%_75%] lg:gap-x-4",
|
||||
"2xl:pl-[184px] lg:pb-4 2xl:pr-[176px] z-[2] relative",
|
||||
"xs:px-4 xs:pb-4 px-1 pb-8",
|
||||
"flex justify-center items-start"
|
||||
)}
|
||||
>
|
||||
<div className="flex flex-col gap-1.5 pt-1 xs:pt-4 lg:py-4">
|
||||
<div className="flex flex-col gap-[10px]">
|
||||
<IconHeadline title="Documentation" icon={<BookIcon />} />
|
||||
<h2 className="text-medusa-fg-base text-h1 text-pretty w-full md:w-2/3 lg:w-full">
|
||||
Learn how to build Medusa projects. Explore our guides.
|
||||
</h2>
|
||||
</div>
|
||||
<Card
|
||||
type="mini"
|
||||
title="Get started"
|
||||
text="Introduction"
|
||||
themeImage={{
|
||||
light: basePathUrl("/images/get-started-card.png"),
|
||||
dark: basePathUrl("/images/get-started-card-dark.png"),
|
||||
}}
|
||||
href={"/learn"}
|
||||
/>
|
||||
</div>
|
||||
<HomepageCodeTabs />
|
||||
<div className="pt-4 hidden lg:flex flex-col gap-0.5">
|
||||
<IconHeadline
|
||||
title="Optimized for Customizations"
|
||||
icon={<WindowPaintbrushIcon />}
|
||||
/>
|
||||
<h2 className="text-medusa-fg-base text-h1 text-pretty">
|
||||
A digital commerce platform with a built-in framework for
|
||||
customizations.
|
||||
</h2>
|
||||
<span className="text-small-plus text-medusa-fg-subtle">
|
||||
Unlike other platforms, Medusa allows you to easily customize and
|
||||
extend the behavior of your commerce platform to always fit your
|
||||
business needs.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default HomepageTopSection
|
||||
Reference in new issue
Block a user