diff --git a/content/_snippets/_moving-fulfillment-orders.mdx b/content/_snippets/_moving-fulfillment-orders.mdx
index 20bb29e..28be69a 100644
--- a/content/_snippets/_moving-fulfillment-orders.mdx
+++ b/content/_snippets/_moving-fulfillment-orders.mdx
@@ -5,7 +5,7 @@ Moving a fulfillment order items to a new fulfillment location is a common order
-#### Move Fulfillment Order Flow
+### Move Fulfillment Order Flow
```mermaid
stateDiagram-v2
direction LR
@@ -20,7 +20,7 @@ Moving fulfillment order items is a 2-step process:
Fulfillment Orders must be `"status": "open"` to be moved to a new location. If the fulfillment order you want to move is `"status": "processing"`, use the [cancellationRequestSend](/docs/admin-api/reference/fulfillment/cancellationRequestSend) endpoint to request cancellation with the current fulfillment location before moving to a new location.
-#### Retrieve Available Locations
+### Retrieve Available Locations
Fulfillment order line items often contain products that are in stock at many locations where they could be fulfilled from. To check what locations fulfillment order items are available at, use the [availableLocationsRetrieve](/docs/admin-api/reference/fulfillment/availableLocationsRetrieve) endpoint.
@@ -46,7 +46,7 @@ Fulfillment order line items often contain products that are in stock at many lo
}
```
-#### Move a Fulfillment Order
+### Move a Fulfillment Order
Once the available locations fulfillment order line items can move, use the [fulfillmentOrdersMove](/docs/admin-api/reference/fulfillment/fulfillmentOrdersMove) endpoint to move all or some of the line items.
diff --git a/content/_snippets/_splitting-fulfillment-orders.mdx b/content/_snippets/_splitting-fulfillment-orders.mdx
index ffe7b89..f32a6cb 100644
--- a/content/_snippets/_splitting-fulfillment-orders.mdx
+++ b/content/_snippets/_splitting-fulfillment-orders.mdx
@@ -4,7 +4,7 @@ Splitting a fulfillment order moves some items onto a second fulfillment order a
Use it when a location can ship part of what it was sent but not all of it. Split off items that cannot be shipped and then fulfill the remaining items. The split items become their own fulfillment order, which can be moved, held, or cancelled separately. The alternative is rejecting the whole request, which sends the order back to the merchant to amend and request fulfillment again.
-#### Split a Fulfillment Order
+### Split a Fulfillment Order
Use the [fulfillmentOrdersSplit](/docs/admin-api/reference/fulfillment/fulfillmentOrdersSplit) endpoint, passing the line items and quantities to move onto the new fulfillment order. Both `id` and `quantity` are required for each entry.
@@ -37,7 +37,7 @@ The response returns both fulfillment orders, so you can see the resulting split
The split fulfillment order inherits the original's status, request status, shipping address, shipping method, and assigned location. A `fulfillment_order_split` event is added to the order timeline.
-#### Split Rules
+### Split Rules
- Each line must belong to the fulfillment order being split.
- `quantity` cannot exceed that line's `fulfillable_quantity`.
diff --git a/content/capabilities.yaml b/content/capabilities.yaml
index 65eee94..8f4002f 100644
--- a/content/capabilities.yaml
+++ b/content/capabilities.yaml
@@ -321,7 +321,7 @@ capabilities:
- /docs/storefront/event-tracking
api_operations: [tag:storefront]
webhooks: []
- skills: [next-theme-dev, next-theme-figma]
+ skills: [next-theme-dev, next-theme-figma, next-theme-design]
status: available
last_verified: 2026-09-03
@@ -437,15 +437,15 @@ capabilities:
- id: agent-skills
title: AI agent skills
summary: >-
- Pre-built skills that give AI coding agents platform knowledge (theme development,
- campaign provisioning and setup, bulk operations, daily ops scans), installable with
- the skills CLI or loadable as plain markdown.
+ Pre-built skills that give AI coding agents platform knowledge (Figma and live-site
+ theme handoffs, theme development, campaign provisioning and setup, bulk operations,
+ daily ops scans), installable with the skills CLI or loadable as plain markdown.
audiences: [developer]
operator_docs: []
developer_docs:
- /docs/skills
api_operations: []
webhooks: []
- skills: [next-theme-figma, next-theme-dev, next-campaigns-create, next-campaigns-setup, next-bulk-fulfill, next-bulk-move, next-bulk-subscription, next-ops-scan]
+ skills: [next-theme-figma, next-theme-design, next-theme-dev, next-campaigns-create, next-campaigns-setup, next-bulk-fulfill, next-bulk-move, next-bulk-subscription, next-ops-scan]
status: available
last_verified: 2026-09-14
diff --git a/content/docs/admin-api/guides/exports.mdx b/content/docs/admin-api/guides/exports.mdx
index 5c66007..b9b9b31 100644
--- a/content/docs/admin-api/guides/exports.mdx
+++ b/content/docs/admin-api/guides/exports.mdx
@@ -14,7 +14,7 @@ The Exports API allows you to generate and download bulk data exports from your
Exports are processed asynchronously. After creating an export, you'll need to poll for completion before downloading the file.
-### Export Flow
+## Export Flow
```mermaid
sequenceDiagram
@@ -32,7 +32,7 @@ Creating and downloading an export is a 3-step process:
2. Create a new export using the [exportsCreate](/docs/admin-api/reference/exports/exportsCreate) endpoint with your desired type and date range.
3. When you receive the `export.created` webhook, download the file using the [exportsDownloadRetrieve](/docs/admin-api/reference/exports/exportsDownloadRetrieve) endpoint.
-### Available Export Types
+## Available Export Types
Use the [exportsTypesRetrieve](/docs/admin-api/reference/exports/exportsTypesRetrieve) endpoint to list all available export types, or reference the table below.
@@ -52,7 +52,7 @@ Use the [exportsTypesRetrieve](/docs/admin-api/reference/exports/exportsTypesRet
| `fulfillment_list` | Fulfillments |
| `fulfillment_line_items` | Fulfillment Line Items |
-### Create an Export
+## Create an Export
To create a new export, send a POST request to the [exportsCreate](/docs/admin-api/reference/exports/exportsCreate) endpoint with the export `type` and date range.
@@ -78,7 +78,7 @@ The response returns the export object with a `pending` status.
}
```
-### Poll Export Status
+## Poll Export Status
After creating an export, poll the [exportsRetrieve](/docs/admin-api/reference/exports/exportsRetrieve) endpoint until the `status` changes from `pending` to `available`.
@@ -98,7 +98,7 @@ After creating an export, poll the [exportsRetrieve](/docs/admin-api/reference/e
Avoid polling too frequently. Checking every couple of minutes is sufficient for pending exports. For a more efficient approach, subscribe to the `export.created` [webhook event](/docs/webhooks) to be notified immediately when an export is available for download.
-### Download Export File
+## Download Export File
Once the export status is `available`, use the [exportsDownloadRetrieve](/docs/admin-api/reference/exports/exportsDownloadRetrieve) endpoint to get a download URL for the CSV file.
@@ -112,7 +112,7 @@ Once the export status is `available`, use the [exportsDownloadRetrieve](/docs/a
Download URLs are temporary signed URLs. Fetch the file promptly after retrieving the URL. If the URL expires, request a new one from the download endpoint.
-### Export Webhooks
+## Export Webhooks
Subscribe to the `export.created` [webhook event](/docs/webhooks) to be notified immediately when an export is available for download. The webhook payload includes the export object data, allowing you to proceed directly to downloading the file without additional API calls.
@@ -121,7 +121,7 @@ Using the `export.created` webhook is the recommended approach for automated exp
-### List Exports
+## List Exports
Use the [exportsList](/docs/admin-api/reference/exports/exportsList) endpoint to retrieve previous exports with optional filtering by type and creation date.
diff --git a/content/docs/admin-api/guides/external-checkout.mdx b/content/docs/admin-api/guides/external-checkout.mdx
index ce99a16..6f3cce3 100644
--- a/content/docs/admin-api/guides/external-checkout.mdx
+++ b/content/docs/admin-api/guides/external-checkout.mdx
@@ -21,7 +21,7 @@ stateDiagram-v2
upsell --> Confirmation
```
-### Create Cart
+## Create Cart
Carts are the starting point for all orders, carts are essentially draft orders waiting to be converted into orders. Creating the cart is a vital step in capturing leads and setting up abandoned cart flows.
@@ -57,7 +57,7 @@ Carts are the starting point for all orders, carts are essentially draft orders
- Attribution added to a cart is carried over to the Orders and Subscriptions created on the users next order, you do not need to pass this data on the order request.
- If you need to capture an address with the cart, use the [usersAddressesCreate](/docs/admin-api/reference/customers/usersAddressesCreate) endpoint which will create a default address for the user.
-### Create Order
+## Create Order
Creating an order is the core resource in an external checkout flow, see the example below to familiarize yourself with the [ordersCreate](/docs/admin-api/reference/orders/ordersCreate) API endpoint.
```json title="Request" http-method="POST" http-target="https://{store}.29next.store/api/admin/orders/"
@@ -99,7 +99,7 @@ Creating an order is the core resource in an external checkout flow, see the exa
- If you already created an address for the user, pass `use_default_shipping_address` and `use_default_billing_address` as true to use their default address for the order.
- For additional payment methods, see the [Payment Methods](/docs/admin-api/guides/payment-methods) guides — [Bankcard](/docs/admin-api/guides/payment-methods/bankcard), [3DS2](/docs/admin-api/guides/payment-methods/bankcard#3d-secure-3ds2), [Apple Pay](/docs/admin-api/guides/payment-methods/apple-pay), [PayPal](/docs/admin-api/guides/payment-methods/paypal), [Klarna](/docs/admin-api/guides/payment-methods/klarna), [Affirm](/docs/admin-api/guides/payment-methods/affirm), [Afterpay](/docs/admin-api/guides/payment-methods/afterpay), [Twint](/docs/admin-api/guides/payment-methods/twint), [Swish](/docs/admin-api/guides/payment-methods/swish), [Bancontact](/docs/admin-api/guides/payment-methods/bancontact), and [SEPA](/docs/admin-api/guides/payment-methods/sepa-debit).
-### Add Upsells
+## Add Upsells
Add additional products (line items) to the original order through the [ordersAddLineItemsCreate](/docs/admin-api/reference/orders/ordersAddLineItemsCreate) API. Adding items to the order will automatically re-use the order's initial payment method to collect payment for the additional products.
@@ -122,7 +122,7 @@ Check `supports_post_purchase_upsells` on the initial order create response befo
The `ordersAddLineItemsCreate` API requires that the order initial **payment method** supports merchant initiated charges. See the [Payment Methods](/docs/admin-api/guides/payment-methods) capability matrix for which methods support upsells.
-### Cart / Order / Upsell lines Detail
+## Cart / Order / Upsell lines Detail
Cart, Order, and Upsell line items represent the products the customer is purchasing. When an order is created, the product fulfillment location will be automatically chosen based on product stock records and inventory availability.
```json title="Specify Line Items and Currency"
@@ -140,7 +140,7 @@ Cart, Order, and Upsell line items represent the products the customer is purcha
Ensure you use the variant product ID for order line items. **Single variant products still contain a variant product future product management to add additional variants.**
-#### Subscription Line Items
+### Subscription Line Items
Lines also accept an optional `subscription` object to specify a subscription that will be automatically created after the initial order is successfully created.
@@ -165,7 +165,7 @@ Subscription line items have two `price` fields available. The order line item l
Orders with Subscription line items **must have an initial payment** (order total > 0.00) to validate and retain the bankcard for future usage.
-#### Custom Line Item Properties
+### Custom Line Item Properties
Lines accept an optional `properties` object of key/value pairs to capture customization details for personalized or made-to-order products, such as an engraving, monogram, or gift message. The values are stored on the line item and persist to the created order (and to the subscription line item when the line creates a subscription).
@@ -185,7 +185,7 @@ Lines accept an optional `properties` object of key/value pairs to capture custo
Line item `properties` are used to determine the uniqueness of line item products and flow all the way through to fulfillment order line items for customized product fulfillment.
-### Cart / Order User Detail
+## Cart / Order User Detail
The `user` object on carts/orders represents the **customer** which includes their contact details. Below are the recommended fields to pass for the user for ease of use and support of external integrations that may rely on the data, i.e. `user_agent`.
@@ -207,7 +207,7 @@ Users are first checked for an existing user by `email` before creating a new us
**It is not recommended to pass `phone_number` directly on the user when creating a cart or order, we recommend passing a local phone number in the `shipping_address` instead.** Address fields have country context, which allows local phone numbers to be passed and converted to [E.164 format](https://en.wikipedia.org/wiki/E.164) before being saved. A `phone_number` passed to the `user` object directly must be in E.164 format.
-### Cart / Order Attribution Detail
+## Cart / Order Attribution Detail
Cart and Order `attribution` object sets the [marketing attribution](https://docs.nextcommerce.com/docs/features/offers/marketing-attribution) on the order for tracking the source of orders and use in orders reporting. You can also pass in [metadata](https://docs.nextcommerce.com/docs/build-a-store/technical-settings/metadata-fields-and-tags) fields that are configured on the store to track custom attribution parameters and integrate external tracking platforms.
```json title="Attribution Detail"
@@ -219,7 +219,7 @@ Cart and Order `attribution` object sets the [marketing attribution](https://doc
}
```
-### Order Shipping Detail
+## Order Shipping Detail
```json title="Shipping Detail"
"shipping_code": "default",
@@ -227,7 +227,7 @@ Cart and Order `attribution` object sets the [marketing attribution](https://doc
```
The `shipping_code` is an optional field to specify the Shipping Method to be used for the order, **if not passed, the cheapest Shipping Method will be used**. `shipping_price` is also optional and provides a way to override the configured price for the Shipping Method of the order allowing you to discount or charge an upsell for shipping on the order.
-### Order Addresses Detail
+## Order Addresses Detail
The `shipping_address` object on the order represents the address where the order will be shipped, and similarly for the `billing_address`. The first `shipping_address` and `billing_address` created for a user is automatically set as their default shipping and billing address, [see API Reference](/docs/admin-api/reference/orders/ordersCreate).
@@ -250,7 +250,7 @@ Use `billing_same_as_shipping_address` to forego having to pass a full duplicate
- User `phone_number` is automatically saved from the user's first address if they do not have an existing `phone_number`.
- In a "Two Step" flow where the customer address is collected before creating the order, create an address for the user and then pass the `use_default_shipping_address` and `use_default_billing_address` as true on the `orders_create` request.
-### Order Payment Detail
+## Order Payment Detail
The order `payment_method` and `payment_details` objects work in tandem to specify the payment method for the order and provide any additional data that may be required per payment method.
@@ -266,14 +266,14 @@ The example below uses a [Test Card Token](/docs/admin-api/guides/testing-guide)
```
To route the order to a specific gateway or gateway group, include `payment_gateway` or `payment_gateway_group` (an id, never both) inside `payment_details`. See [Gateway Routing](/docs/admin-api/guides/payment-methods/bankcard#gateway-routing) in the Bankcard guide.
-#### Statement Descriptor
+### Statement Descriptor
Merchants have the option to pass a custom `statement_descriptor` on orders so the end customer will more easily recognize the charge on their card bank statement. Using this field will override all subsequent transactions for the bankcard, even across payment gateways.
Descriptors can be up to 22 alphanumeric characters, spaces, and these special characters: `& , . - #`. Passing in an invalid statement descriptor will be ignored.
-#### Payment Method Guides
-See the [**Payment Methods**](/docs/admin-api/guides/payment-methods) section for method-specific guides on creating orders, plus the full capability matrix (flow type, express checkout, upsell, and subscription support per method).
+### Payment Method Guides
+See the [Payment Methods](/docs/admin-api/guides/payment-methods) section for method-specific guides on creating orders, plus the full capability matrix (flow type, express checkout, upsell, and subscription support per method).
**[View all payment methods →](/docs/admin-api/guides/payment-methods)**
diff --git a/content/docs/admin-api/guides/order-management.mdx b/content/docs/admin-api/guides/order-management.mdx
index 766b246..1a9f1a8 100644
--- a/content/docs/admin-api/guides/order-management.mdx
+++ b/content/docs/admin-api/guides/order-management.mdx
@@ -15,7 +15,7 @@ Order management operations can be automated through the Admin API for more effi
Below are best practices and guides for common scenarios merchants and partners use to manage orders on the Admin API.
-### Order Items Editing
+## Order Items Editing
Editing items on an order is common practice, such as swapping products purchased for a different size or color with the same value without needing to collect payment or create a refund.
@@ -24,7 +24,7 @@ Order editing APIs are only available on 2024-04-01 API Version and above, if yo
Order editing APIs also do not affect order payment within each request. To remove items with an associated refund, see [order refunds](#order-refunds). Using order edit APIs can result in the customer owing or the merchant owing to the customer.
-#### Line Item Quantities Explained
+### Line Item Quantities Explained
Order line items have 4 quantity attributes that represent quantities at different states in an order life cycle.
@@ -46,7 +46,7 @@ Order line items have 4 quantity attributes that represent quantities at differe
]
```
-### Swap Items Flow
+## Swap Items Flow
```mermaid
stateDiagram-v2
@@ -68,7 +68,7 @@ Swapping Items on an order is a 4 step process:
4. [Collect payment for an outstanding](#collect-payment-for-outstanding-balance) balance using the [ordersCollectPaymentCreate](/docs/admin-api/reference/orders/ordersCollectPaymentCreate) endpoint.
-#### Update Existing Line Item
+### Update Existing Line Item
Below is an example API call to change the quantity of a line item to 1. If the existing quantity was 2, this would remove 1 quantity, can also be used to increase line item quantity. This endpoint only accepts quantity changes, to change the product or price, see [ordersLinesCreate](/docs/admin-api/reference/orders/ordersLinesCreate) endpoint.
@@ -79,7 +79,7 @@ Below is an example API call to change the quantity of a line item to 1. If the
}
```
-#### Remove Full Line Item
+### Remove Full Line Item
Below is an example DELETE request to the [ordersLinesDestroy](/docs/admin-api/reference/orders/ordersLinesDestroy) endpoint to remove a line item.
@@ -93,7 +93,7 @@ Line items have `editable_quantity` which represents the item quantity not alrea
**If `editable_quantity` is `0`, the line item cannot be edited.**
-#### Create New Line Item
+### Create New Line Item
Below is an example POST request to the [ordersLinesCreate](/docs/admin-api/reference/orders/ordersLinesCreate) endpoint to create a new line item.
@@ -106,7 +106,7 @@ Below is an example POST request to the [ordersLinesCreate](/docs/admin-api/refe
}
```
-#### Collect Payment for Outstanding Balance
+### Collect Payment for Outstanding Balance
Orders can have an outstanding balance owed by the customer as a result of changing items on the order. To collect the outstanding balance, use the [ordersCollectPaymentCreate](/docs/admin-api/reference/orders/ordersCollectPaymentCreate) endpoint to initiate a payment transaction with the order's initial payment method.
@@ -116,11 +116,11 @@ Orders can have an outstanding balance owed by the customer as a result of chang
}
```
-### Order Refunds
+## Order Refunds
Order management actions that require refunding and removing items from an order can be done through the refund flow. The refund flow is especially useful when creating partial refunds or creating refunds for items that have already shipped to the customer.
-#### Refund Flow
+### Refund Flow
```mermaid
stateDiagram-v2
direction LR
@@ -140,7 +140,7 @@ Refunding specific items of an order is a 3-step process:
Order Refund Calculate APIs are only available on `2024-04-01` version and newer. See [API Versioning](/docs/admin-api#versioning) for how to specify a version in your requests.
-#### Retrieve Order Lines
+### Retrieve Order Lines
Below is an abbreviated example request to [ordersRetrieve](/docs/admin-api/reference/orders/ordersRetrieve) endpoint to get the line items of the order.
@@ -158,7 +158,7 @@ Below is an abbreviated example request to [ordersRetrieve](/docs/admin-api/refe
Order payments must be captured in order to create partial refunds, uncaptured payments cannot be partially refunded.
-#### Calculate Refund
+### Calculate Refund
Call the [ordersRefundCalculateCreate](/docs/admin-api/reference/orders/ordersRefundCalculateCreate) endpoint with your line items to calculate the refund and see which initial payment transactions will be refunded.
@@ -217,7 +217,7 @@ Below is the response from the [ordersRefundCalculateCreate](/docs/admin-api/ref
When an order has [split fulfillment](#split-fulfillment-orders) across multiple locations, its lines can be refunded at each of them. Calculate returns the `line_id` once per location, each with its own `refundable_quantity`. Pass the matching `location_id` when you create the refund.
-#### Create Refund
+### Create Refund
We're now ready to create a refund using the [ordersRefundCreate](/docs/admin-api/reference/orders/ordersRefundCreate) endpoint, see request details below.
@@ -267,7 +267,7 @@ Depending on the product type and status of the line items being refunded, there
- If unfulfilled, restock_type must be `cancel`.
- If fulfilled, restock_type must be `no_restock`.
-### Update Shipping Address
+## Update Shipping Address
Updating an order shipping address is a common task that can be done with a PATCH request to the [ordersUpdate](/docs/admin-api/reference/orders/ordersUpdate) endpoint.
@@ -287,7 +287,7 @@ Updating an order shipping address is a common task that can be done with a PATC
Updating an order shipping address should be done **before** the order is sent to a fulfillment location for fulfillment. If the order has already been accepted and processing, send a a [cancellationRequestSend](/docs/admin-api/reference/fulfillment/cancellationRequestSend) request and then [fulfillmentRequestSend](/docs/admin-api/reference/fulfillment/fulfillmentRequestSend) after you've updated the shipping address.
-### Request Fulfillment
+## Request Fulfillment
Fulfillment can be requested immediately through the [fulfillmentRequestSend](/docs/admin-api/reference/fulfillment/fulfillmentRequestSend) for cases that you'd like to immediately send the fulfillment order to the fulfillment location for fulfillment.
@@ -305,7 +305,7 @@ Fulfillment can be requested immediately through the [fulfillmentRequestSend](/d
}
```
-### Hold Fulfillment
+## Hold Fulfillment
Holding fulfillment for an order while waiting for additional review or making adjustments to the order before sending to the fulfillment location for shipping.
@@ -326,7 +326,7 @@ stateDiagram-v2
}
```
-### Cancel Fulfillment
+## Cancel Fulfillment
Canceling a fulfillment order that is already accepted and processing with a fulfillment location is a common order management task to stop fulfillment or as a prerequisite step to moving a fulfillment order to a new location.
@@ -348,15 +348,15 @@ stateDiagram-v2
}
```
-### Move Fulfillment Orders
+## Move Fulfillment Orders
-### Split Fulfillment Orders
+## Split Fulfillment Orders
-### Add Fulfillment Tracking
+## Add Fulfillment Tracking
Adding tracking information to a fulfillment order marks it as fulfilled and optionally notifies the customer with shipment tracking details. Use the [fulfillmentsCreate](/docs/admin-api/reference/fulfillment/fulfillmentsCreate) endpoint to create a fulfillment with tracking info.
@@ -376,7 +376,7 @@ Adding tracking information to a fulfillment order marks it as fulfilled and opt
The `tracking_info` field accepts an array, allowing you to add multiple tracking numbers for a single fulfillment order when a shipment is split across multiple packages.
-### Cancel Order
+## Cancel Order
Canceling an order is a common order management task when you need to cancel the entire order and refund all payment transactions. To cancel an order, send a request to the [ordersCancelCreate](/docs/admin-api/reference/orders/ordersCancelCreate) endpoint.
diff --git a/content/docs/admin-api/guides/payment-methods/affirm.mdx b/content/docs/admin-api/guides/payment-methods/affirm.mdx
index 6005a26..e8135ab 100644
--- a/content/docs/admin-api/guides/payment-methods/affirm.mdx
+++ b/content/docs/admin-api/guides/payment-methods/affirm.mdx
@@ -13,14 +13,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
Affirm transactions send the customer through an Affirm redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get Affirm set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Affirm using the orders_create API method, you must specify the `payment_method=affirm` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -40,7 +40,7 @@ When creating a new order using Affirm using the orders_create API method, you m
You can optionally provide a `payment_gateway` when creating the order to use an Affirm account connected to a specific gateway.
-### Redirect Customer to Affirm
+## Redirect Customer to Affirm
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on Affirm.
```json title="Response with Payment Complete URL"
@@ -50,13 +50,13 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Upsells are not supported with Affirm payments.
diff --git a/content/docs/admin-api/guides/payment-methods/afterpay.mdx b/content/docs/admin-api/guides/payment-methods/afterpay.mdx
index c238eec..76c1921 100644
--- a/content/docs/admin-api/guides/payment-methods/afterpay.mdx
+++ b/content/docs/admin-api/guides/payment-methods/afterpay.mdx
@@ -11,13 +11,13 @@ import { Callout } from 'fumadocs-ui/components/callout';
Afterpay transactions send the customer through an Afterpay redirect flow, with the resulting order information returned to your application. Before using Afterpay, activate it on the Stripe account connected to the gateway. In the United Kingdom the same method is branded **Clearpay**.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating an order with the `orders_create` API method, specify `payment_method=afterpay` and provide a `payment_return_url`. The `payment_return_url` is your endpoint that receives a POST request containing the final order data.
@@ -36,7 +36,7 @@ When creating an order with the `orders_create` API method, specify `payment_met
You can optionally provide a `payment_gateway` when creating the order to use an Afterpay account connected to a specific gateway.
-### Redirect Customer to Afterpay
+## Redirect Customer to Afterpay
The order response provides a `payment_complete_url`. Redirect the customer to this URL to complete the payment with Afterpay.
@@ -47,16 +47,16 @@ The order response provides a `payment_complete_url`. Redirect the customer to t
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
One-click post-purchase upsells are not supported with Afterpay payments. Afterpay authorizes a single sale and the payment method cannot be reused for a later merchant-initiated charge.
-### Recurring
+## Recurring
Afterpay cannot be used as the payment method for an order with subscription items.
diff --git a/content/docs/admin-api/guides/payment-methods/apple-pay.mdx b/content/docs/admin-api/guides/payment-methods/apple-pay.mdx
index fd0443c..986f2ba 100644
--- a/content/docs/admin-api/guides/payment-methods/apple-pay.mdx
+++ b/content/docs/admin-api/guides/payment-methods/apple-pay.mdx
@@ -15,14 +15,14 @@ For custom checkouts using the Admin API, there are two flows available -- the s
Your store must have a Apple Pay setup and enabled with a gateway to use the Apple Pay payment method. The user device must also be an Apple Device with Touch ID enabled. See more on [displaying Apple Pay buttons](https://developer.apple.com/documentation/apple_pay_on_the_web/displaying_apple_pay_buttons_using_css) or the [Apple Pay Demo](https://applepaydemo.apple.com/).
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Apple Pay, you’ll need to specify the `payment_method=apple_pay` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -37,7 +37,7 @@ When creating a new order using Apple Pay, you’ll need to specify the `payment
}
```
-### Redirect Customer to Payment Complete URL
+## Redirect Customer to Payment Complete URL
The response when creating the order will provide a payment_complete_url. Your application should redirect the customer to this URL for completing the payment on the store's Apple Pay Checkout page.
```json title="Response with Payment Complete URL"
@@ -47,7 +47,7 @@ The response when creating the order will provide a payment_complete_url. Your a
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
diff --git a/content/docs/admin-api/guides/payment-methods/bancontact.mdx b/content/docs/admin-api/guides/payment-methods/bancontact.mdx
index efe86b8..3d13145 100644
--- a/content/docs/admin-api/guides/payment-methods/bancontact.mdx
+++ b/content/docs/admin-api/guides/payment-methods/bancontact.mdx
@@ -14,14 +14,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
Bancontact transactions send the customer through a Bancontact redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get Bancontact set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Bancontact using the orders_create API method, you must specify the `payment_method=bancontact` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -41,7 +41,7 @@ When creating a new order using Bancontact using the orders_create API method, y
You can optionally provide a `payment_gateway` when creating the order to use a Bancontact account connected to a specific gateway.
-### Redirect Customer to Bancontact
+## Redirect Customer to Bancontact
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on Bancontact.
```json title="Response with Payment Complete URL"
@@ -51,13 +51,13 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Upsells are not supported with Bancontact payments.
diff --git a/content/docs/admin-api/guides/payment-methods/google-pay.mdx b/content/docs/admin-api/guides/payment-methods/google-pay.mdx
index becc299..81039b8 100644
--- a/content/docs/admin-api/guides/payment-methods/google-pay.mdx
+++ b/content/docs/admin-api/guides/payment-methods/google-pay.mdx
@@ -15,14 +15,14 @@ For custom checkouts using the Admin API, there are two flows available -- the s
Your store must have a Google Pay setup and enabled with a gateway to use the Google Pay payment method and the user device must use Chrome browser or Android with Google Pay setup.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Google Pay, you’ll need to specify the `payment_method=google_pay` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -40,7 +40,7 @@ When creating a new order using Google Pay, you’ll need to specify the `paymen
To test Google Pay as a payment method, you can use the `test` gateway with your real credit card in your Google Pay account, your card will not be charged.
-### Redirect Customer to Payment Complete URL
+## Redirect Customer to Payment Complete URL
The response when creating the order will provide a payment_complete_url. Your application should redirect the customer to this URL for completing the payment on the store's Google Pay Checkout page.
```json title="Response with Payment Complete URL"
@@ -50,7 +50,7 @@ The response when creating the order will provide a payment_complete_url. Your a
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
diff --git a/content/docs/admin-api/guides/payment-methods/ideal.mdx b/content/docs/admin-api/guides/payment-methods/ideal.mdx
index dba1720..c0199d2 100644
--- a/content/docs/admin-api/guides/payment-methods/ideal.mdx
+++ b/content/docs/admin-api/guides/payment-methods/ideal.mdx
@@ -13,14 +13,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
iDEAL transactions send the customer through a iDEAL redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get iDEAL set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using iDEAL using the orders_create API method, you must specify the `payment_method=ideal` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -39,7 +39,7 @@ When creating a new order using iDEAL using the orders_create API method, you mu
You can optionally provide a `payment_gateway` when creating the order to use a iDEAL account connected to a specific gateway.
-### Redirect Customer to iDEAL
+## Redirect Customer to iDEAL
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on iDEAL.
```json title="Response with Payment Complete URL"
@@ -49,13 +49,13 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Upsells are not supported with iDEAL payments.
diff --git a/content/docs/admin-api/guides/payment-methods/klarna.mdx b/content/docs/admin-api/guides/payment-methods/klarna.mdx
index c6eed0d..cd623fc 100644
--- a/content/docs/admin-api/guides/payment-methods/klarna.mdx
+++ b/content/docs/admin-api/guides/payment-methods/klarna.mdx
@@ -12,14 +12,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
Klarna transactions send the customer through a Klarna redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get Klarna set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Klarna using the orders_create API method, you must specify the `payment_method=klarna` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -39,7 +39,7 @@ When creating a new order using Klarna using the orders_create API method, you m
You can optionally provide a `payment_gateway` when creating the order to use a Klarna account connected to a specific gateway.
-### Redirect Customer to Klarna
+## Redirect Customer to Klarna
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on Klarna.
```json title="Response with Payment Complete URL"
@@ -49,18 +49,18 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Klarna supports one-click upsells through the [ordersAddLineItemsCreate](/docs/admin-api/reference/orders/ordersAddLineItemsCreate) API, enabling additional items to be added to the order with a payment transaction.
-### Recurring
+## Recurring
Klarna via NEXT Payments supports recurring transactions and can be used as a payment method for an order with subscription items.
diff --git a/content/docs/admin-api/guides/payment-methods/link.mdx b/content/docs/admin-api/guides/payment-methods/link.mdx
index 97d24ea..571085c 100644
--- a/content/docs/admin-api/guides/payment-methods/link.mdx
+++ b/content/docs/admin-api/guides/payment-methods/link.mdx
@@ -12,14 +12,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
Link transactions send the customer through a Link redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get Link set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Link using the orders_create API method, you must specify the `payment_method=link` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -39,7 +39,7 @@ When creating a new order using Link using the orders_create API method, you mus
You can optionally provide a `payment_gateway` when creating the order to use a Link account connected to a specific gateway.
-### Redirect Customer to Link
+## Redirect Customer to Link
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on Link.
```json title="Response with Payment Complete URL"
@@ -49,17 +49,17 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Link supports one-click upsells through the [ordersAddLineItemsCreate](/docs/admin-api/reference/orders/ordersAddLineItemsCreate) API, enabling additional items to be added to the order with a payment transaction.
-### Recurring
+## Recurring
Link via Stripe supports recurring transactions and can be used as a payment method for an order with subscription items.
diff --git a/content/docs/admin-api/guides/payment-methods/paypal.mdx b/content/docs/admin-api/guides/payment-methods/paypal.mdx
index 97aaf01..20c2ead 100644
--- a/content/docs/admin-api/guides/payment-methods/paypal.mdx
+++ b/content/docs/admin-api/guides/payment-methods/paypal.mdx
@@ -14,14 +14,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
For custom PayPal checkouts, there are two checkout flows available, the standard method where a user enters their shipping address, chooses products, and then checks out via PayPal; and the "One-Click" method, where the user is not required to enter shipping information before being redirected to PayPal checkout.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using PayPal using the orders_create API method, you must specify the `payment_method=paypal` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -39,7 +39,7 @@ When creating a new order using PayPal using the orders_create API method, you m
You can optionally provide a `paypal_account` when creating the order to use a PayPal account other than the store default PayPal account.
-### Redirect Customer to PayPal
+## Redirect Customer to PayPal
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on PayPal.
```json title="Response with Payment Complete URL"
@@ -49,14 +49,14 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
PayPal supports one-click upsells through the [ordersAddLineItemsCreate](/docs/admin-api/reference/orders/ordersAddLineItemsCreate) API, enabling additional items to be added to the order with a payment transaction.
diff --git a/content/docs/admin-api/guides/payment-methods/sepa-debit.mdx b/content/docs/admin-api/guides/payment-methods/sepa-debit.mdx
index 29588aa..86c3412 100644
--- a/content/docs/admin-api/guides/payment-methods/sepa-debit.mdx
+++ b/content/docs/admin-api/guides/payment-methods/sepa-debit.mdx
@@ -13,14 +13,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
SEPA Direct Debit transactions send the customer through a SEPA Direct Debit redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get SEPA Direct Debit set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using SEPA Direct Debit using the orders_create API method, you must specify the `payment_method=sepa_debit` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -40,7 +40,7 @@ When creating a new order using SEPA Direct Debit using the orders_create API me
You can optionally provide a `payment_gateway` when creating the order to use a SEPA Direct Debit account connected to a specific gateway.
-### Redirect Customer to SEPA Direct Debit
+## Redirect Customer to SEPA Direct Debit
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on SEPA Direct Debit.
```json title="Response with Payment Complete URL"
@@ -50,13 +50,13 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Upsells are not supported with SEPA Direct Debit payments.
diff --git a/content/docs/admin-api/guides/payment-methods/swish.mdx b/content/docs/admin-api/guides/payment-methods/swish.mdx
index 5f224f8..d18033a 100644
--- a/content/docs/admin-api/guides/payment-methods/swish.mdx
+++ b/content/docs/admin-api/guides/payment-methods/swish.mdx
@@ -11,13 +11,13 @@ import { Callout } from 'fumadocs-ui/components/callout';
Swish transactions send the customer through a hosted payment flow, with the resulting order information returned to your application. Before using Swish, make sure it is enabled for the NEXT Payments account and store. Swish is available for eligible Swedish checkout traffic in SEK.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating an order with the `orders_create` API method, specify `payment_method=swish` and provide a `payment_return_url`. The `payment_return_url` is your endpoint that receives a POST request containing the final order data.
@@ -36,7 +36,7 @@ When creating an order with the `orders_create` API method, specify `payment_met
You can optionally provide a `payment_gateway` or `payment_gateway_group` to route the order through a specific eligible NEXT Payments configuration.
-### Redirect Customer to Swish
+## Redirect Customer to Swish
The order response provides a `payment_complete_url`. Redirect the customer to this URL to complete the payment with Swish.
@@ -47,16 +47,16 @@ The order response provides a `payment_complete_url`. Redirect the customer to t
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
One-click post-purchase upsells are not supported with Swish payments.
-### Recurring
+## Recurring
Swish cannot be used as the payment method for subscription items.
diff --git a/content/docs/admin-api/guides/payment-methods/twint.mdx b/content/docs/admin-api/guides/payment-methods/twint.mdx
index 6fb4253..6d90282 100644
--- a/content/docs/admin-api/guides/payment-methods/twint.mdx
+++ b/content/docs/admin-api/guides/payment-methods/twint.mdx
@@ -13,14 +13,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
Twint transactions send the customer through a Twint redirect flow, with the resulting order information provided back to your application. Below are the steps needed to get Twint set up and working on the Admin API.
-### API Payment Redirect Flow
+## API Payment Redirect Flow
import RedirectPaymentFlow from '../../../../_snippets/_redirect-payment-flow.mdx';
-### Create Order on Admin API
+## Create Order on Admin API
When creating a new order using Twint using the orders_create API method, you must specify the `payment_method=twint` as well as provide a `payment_return_url`. The `payment_return_url` is your endpoint that will receive a POST request containing the final order data.
@@ -40,7 +40,7 @@ When creating a new order using Twint using the orders_create API method, you mu
You can optionally provide a `payment_gateway` when creating the order to use a Twint account connected to a specific gateway.
-### Redirect Customer to Twint
+## Redirect Customer to Twint
The response when creating the order will provide a `payment_complete_url`. Your application should redirect the customer to this URL for completing the payment on Twint.
```json title="Response with Payment Complete URL"
@@ -50,18 +50,18 @@ The response when creating the order will provide a `payment_complete_url`. Your
}
```
-### Receiving Order Data
+## Receiving Order Data
import RedirectPaymentStep3 from '../../../../_snippets/_redirect-payment-flows-step-3.mdx';
-### Upsells
+## Upsells
Twint supports one-click upsells through the [ordersAddLineItemsCreate](/docs/admin-api/reference/orders/ordersAddLineItemsCreate) API, enabling additional items to be added to the order with a payment transaction.
-### Recurring
+## Recurring
Twint via NEXT Payments supports recurring transactions and can be used as a payment method for an order with subscription items.
diff --git a/content/docs/admin-api/guides/product-management.mdx b/content/docs/admin-api/guides/product-management.mdx
index bcdbb25..af4c150 100644
--- a/content/docs/admin-api/guides/product-management.mdx
+++ b/content/docs/admin-api/guides/product-management.mdx
@@ -12,7 +12,7 @@ Catalogue management can be automated through the Admin API to sync products fro
Below are best practices and guides for common scenarios merchants and partners use to manage products on the Admin API. Requests need the `catalogue:write` scope, and reading products needs `catalogue:read`.
-### Product Model
+## Product Model
Every product is a parent with one or more variants. The product holds the title, description, images, categories and `variant_attributes`. Each variant holds the `sku`, `prices`, `stockrecords`, `track_stock`, `allow_backorders` and its own `image` chosen from the product's images.
@@ -24,7 +24,7 @@ In responses, `structure` is `parent` on the product and `child` on each entry i
Prices and stockrecords are always on the variant. Creating a price on a parent product is rejected with "This action is not allowed on parent products." Use the variant `id` from the `variants` array when calling the prices and stockrecords endpoints.
-### Create a Simple Product
+## Create a Simple Product
Create a product sold in one form with a single POST to the [productsCreate](/docs/admin-api/reference/products/productsCreate) endpoint. Send no `variant_attributes` and exactly one entry in `variants` carrying the SKU, price and stock for its default variant.
@@ -67,14 +67,14 @@ The response is the full product with `id`, `slug`, `url` and the default varian
Every variant you create must include `prices` and `stockrecords`. The only exception is a variant with `requires_shipping` set to `false`, which gets a stockrecord at your default location automatically.
-### Create a Product with Variants
+## Create a Product with Variants
A product sold in several options is a parent with `variant_attributes` such as Color and Size, and one variant per combination. There are two ways to create it:
- **Single request** creates the parent and its variants in one call. Use it when the variants share the parent's images.
- **Step by step** creates the parent, uploads images, then creates each variant. Use it when each variant needs its own image, because a variant's `image` is an ID from the parent's image list and cannot be set inside the nested `variants` array.
-#### Single Request
+### Single Request
Send `variant_attributes` and `variants` together to the [productsCreate](/docs/admin-api/reference/products/productsCreate) endpoint. Each variant picks one value for every attribute in `variant_attribute_values`.
@@ -131,7 +131,7 @@ Each `value` in `variant_attribute_values` must be one of the `values` listed on
You do not have to create every combination up front. Add the rest later with the [Add a Variant](#add-a-variant) flow.
-#### Step by Step
+### Step by Step
Creating a product with an image on each variant is a 3 step process:
@@ -149,7 +149,7 @@ stateDiagram-v2
2. Upload each image to the parent using the [productsImageCreate](/docs/admin-api/reference/products/productsImageCreate) endpoint and keep the returned image `id`.
3. Create each variant using the [productsVariantCreate](/docs/admin-api/reference/products/productsVariantCreate) endpoint with `image` set to one of those IDs.
-#### Step 1: Create the Parent
+### Step 1: Create the Parent
```json title="Create Parent Product" http-method="POST" http-target="https://{store}.29next.store/api/admin/products/"
{
@@ -169,7 +169,7 @@ stateDiagram-v2
}
```
-#### Step 2: Upload the Images
+### Step 2: Upload the Images
```json title="Upload Product Image" http-method="POST" http-target="https://{store}.29next.store/api/admin/products/{id}/images/"
{
@@ -182,7 +182,7 @@ stateDiagram-v2
The response carries the image `id` you need in the next step.
-#### Step 3: Create the Variants
+### Step 3: Create the Variants
```json title="Create Variant" http-method="POST" http-target="https://{store}.29next.store/api/admin/products/{id}/variants/"
{
@@ -212,7 +212,7 @@ The response carries the image `id` you need in the next step.
The response from [productsVariantCreate](/docs/admin-api/reference/products/productsVariantCreate) is the full list of the parent's variants, not only the one you created. Match yours by `sku` or `metadata` to read back its `id`.
-### Add a Variant
+## Add a Variant
Add a variant to an existing product with the [productsVariantCreate](/docs/admin-api/reference/products/productsVariantCreate) endpoint, using the same request as the step by step flow above. The attribute and value must already exist on the parent, so add a new value first with a PATCH to the [productsPartialUpdate](/docs/admin-api/reference/products/productsPartialUpdate) endpoint.
@@ -231,7 +231,7 @@ Add a variant to an existing product with the [productsVariantCreate](/docs/admi
`variant_attributes` on an update is the complete list. Any attribute you leave out is deleted from the product, and any value you leave out of `values` is deleted from that attribute. Always send every attribute and every value you want to keep.
-### Product Images
+## Product Images
Images belong to the product, not the variant. Upload one from a URL with `src`, or from base64 data with `attachment`, using the [productsImageCreate](/docs/admin-api/reference/products/productsImageCreate) endpoint. Send one or the other, not both.
@@ -248,7 +248,7 @@ Images belong to the product, not the variant. Upload one from a URL with `src`,
The image with `display_order` of `0` is the product's primary image. Change the order with a PATCH to the [productsImageUpdate](/docs/admin-api/reference/products/productsImageUpdate) endpoint.
-#### Assign an Image to Variants
+### Assign an Image to Variants
Set which variants show an image with `variants` on the [productsImageUpdate](/docs/admin-api/reference/products/productsImageUpdate) endpoint. A variant with no assigned image shows all of the parent's images.
@@ -260,7 +260,7 @@ Set which variants show an image with `variants` on the [productsImageUpdate](/d
The same link can be made from the variant side by setting `image` on the [productsVariantsPartialUpdate](/docs/admin-api/reference/products/productsVariantsPartialUpdate) endpoint.
-#### Remove an Image
+### Remove an Image
```json title="Remove Image" http-method="DELETE" http-target="https://{store}.29next.store/api/admin/products/{id}/images/{imageId}/"
{}
@@ -270,7 +270,7 @@ The same link can be made from the variant side by setting `image` on the [produ
Posting an image to a variant `id` is rejected with "The product cannot be a variant." Upload to the parent and assign it as shown above.
-### Pricing
+## Pricing
Each variant has one price per currency. Add a currency to a variant with the [productsPricesCreate](/docs/admin-api/reference/products/productsPricesCreate) endpoint, using the variant `id` in the path.
@@ -298,13 +298,13 @@ Remove a currency with the [productsPricesDestroy](/docs/admin-api/reference/pro
A price is rejected with "Currency is not available." when the store does not have that currency enabled, and with "This currency already exists." when the variant already has a price in it. Use PATCH to change an existing price.
-### Inventory
+## Inventory
Stock is tracked per variant per fulfillment location in a stockrecord. Find your location IDs with the [locationsList](/docs/admin-api/reference/fulfillment/locationsList) endpoint.
Two flags on the variant control how stock is applied. `track_stock` turns inventory tracking on, and `allow_backorders` keeps the variant purchasable when `num_in_stock` reaches zero.
-#### Update Stock Level
+### Update Stock Level
Find the stockrecord `id` in the variant's `stockrecords` array, then PATCH the [stockrecordsPartialUpdate](/docs/admin-api/reference/products/stockrecordsPartialUpdate) endpoint.
@@ -315,7 +315,7 @@ Find the stockrecord `id` in the variant's `stockrecords` array, then PATCH the
}
```
-#### Add a Location to a Variant
+### Add a Location to a Variant
```json title="Create Stockrecord" http-method="POST" http-target="https://{store}.29next.store/api/admin/stockrecords/"
{
@@ -326,7 +326,7 @@ Find the stockrecord `id` in the variant's `stockrecords` array, then PATCH the
}
```
-#### Remove a Location from a Variant
+### Remove a Location from a Variant
Delete the stockrecord with the [stockrecordsDestroy](/docs/admin-api/reference/products/stockrecordsDestroy) endpoint to stop fulfilling a variant from that location.
@@ -338,7 +338,7 @@ Delete the stockrecord with the [stockrecordsDestroy](/docs/admin-api/reference/
A variant must keep at least one stockrecord, so the last one cannot be deleted. When `track_stock` is on, a stockrecord with `num_allocated` above zero cannot be deleted until those orders are fulfilled or cancelled. Both cases return a validation error and leave the stockrecord in place.
-#### Find Low or Out of Stock Items
+### Find Low or Out of Stock Items
The [stockrecordsList](/docs/admin-api/reference/products/stockrecordsList) endpoint filters on `inventory_availability` with `in_stock`, `low_stock`, `out_of_stock` or `untracked`, and on `location_id`, `sku` and `search_text`.
@@ -348,7 +348,7 @@ The [stockrecordsList](/docs/admin-api/reference/products/stockrecordsList) endp
Each stockrecord in the response carries `num_in_stock`, `num_allocated` for units reserved by open orders, and `net_stock_level` for what remains sellable.
-### Subscription Products
+## Subscription Products
Set `enable_subscription` on the product to allow it in subscription orders. When it is `true`, `interval` and `interval_counts` are required.
@@ -362,7 +362,7 @@ Set `enable_subscription` on the product to allow it in subscription orders. Whe
Set the subscription price per currency on each variant with `subscription` in [Pricing](#pricing). See [API Subscription Management](/docs/admin-api/guides/subscription-management) for managing the subscriptions themselves.
-### Organize the Catalogue
+## Organize the Catalogue
Create a category with the [categoriesCreate](/docs/admin-api/reference/products/categoriesCreate) endpoint. A `slug` with `/` creates the parent categories in the path, so `apparel/tees` creates Apparel and nests Tees under it.
@@ -391,7 +391,7 @@ Assign categories, recommended products and ordering on the product.
`recommended_products` accepts product IDs only. Passing a variant `id` is rejected.
-### Visibility and SEO
+## Visibility and SEO
`is_public` controls whether the product shows in search results and catalogue listings. Set it to `false` for a product that should stay purchasable through a direct link, a campaign or an upsell without being discoverable.
@@ -405,7 +405,7 @@ Assign categories, recommended products and ordering on the product.
}
```
-### Sync From an External System
+## Sync From an External System
When another system owns the catalogue, key each product on its SKU and store the external ID in `metadata` so later runs can find it without a lookup table.
@@ -470,7 +470,7 @@ stateDiagram-v2
Metadata keys must be defined first with the [metadataCreate](/docs/admin-api/reference/metadata/metadataCreate) endpoint, with `object` set to `product` or `variant`. To react to changes made in the dashboard, subscribe to product [webhooks](/docs/webhooks).
-### Retire a Product
+## Retire a Product
To stop selling a product without losing its order history, set `is_public` to `false` and remove it from the campaigns and offers that reference it. A variant that has been purchased should be kept for the same reason. Remove its variant attribute values instead of deleting it so it no longer appears as a selectable option.
diff --git a/content/docs/admin-api/guides/subscription-management.mdx b/content/docs/admin-api/guides/subscription-management.mdx
index 0cadafb..661113a 100644
--- a/content/docs/admin-api/guides/subscription-management.mdx
+++ b/content/docs/admin-api/guides/subscription-management.mdx
@@ -13,7 +13,7 @@ Subscriptions management can be done through Admin API to automate business proc
Subscription management actions most often times will only affect future renewals orders/charges of the subscription.
-### Create Subscription
+## Create Subscription
Subscriptions can be created directly through the [subscriptionsCreate](/docs/admin-api/reference/subscriptions/subscriptionsCreate) Admin API endpoint for scenarios such as custom order flows or importing subscriptions from another platform.
@@ -46,11 +46,11 @@ Subscriptions can be created directly through the [subscriptionsCreate](/docs/ad
}
```
-### Updating Products & Pricing
+## Updating Products & Pricing
Updating subscription recurring items and pricing can be done through [subscriptionLinesCreate](/docs/admin-api/reference/subscriptions/subscriptionsLinesCreate), [subscriptionLinesUpdate](/docs/admin-api/reference/subscriptions/subscriptionsLinesUpdate), and [subscriptionsLinesDestroy](/docs/admin-api/reference/subscriptions/subscriptionsLinesDestroy) endpoints.
-**Adding an Additional Product**
+### Adding an Additional Product
To add a new product to a subscription, use the [subscriptionLinesCreate](/docs/admin-api/reference/subscriptions/subscriptionsLinesCreate) Admin API endpoint with the product, price, and quantity details.
@@ -62,7 +62,7 @@ To add a new product to a subscription, use the [subscriptionLinesCreate](/docs/
}
```
-**Updating an Existing Line Item Product Price**
+### Updating an Existing Line Item Product Price
To update and existing product price and quantity on a subscription line, use the [subscriptionsLinesUpdate](/docs/admin-api/reference/subscriptions/subscriptionsLinesUpdate) Admin API endpoint with the new price, and new quantity details.
@@ -73,7 +73,7 @@ To update and existing product price and quantity on a subscription line, use th
}
```
-**Removing a Product**
+### Removing a Product
To remove a product from a subscription, send a DELETE request to the [subscriptionsLinesDestroy](/docs/admin-api/reference/subscriptions/subscriptionsLinesDestroy) endpoint to remove the line item (ie the product) from future renewal orders created from the subscription.
@@ -84,7 +84,7 @@ To remove a product from a subscription, send a DELETE request to the [subscript
Subscriptions must have at least one line item with a product, you can alternatively cancel the subscription to stop all future renewals.
-### Updating Renewal Schedule
+## Updating Renewal Schedule
Changing the renewal schedule of a subscription can be achieved with a PATCH request to the [subscriptionsPartialUpdate](/docs/admin-api/reference/subscriptions/subscriptionsPartialUpdate) endpoint with a new `interval` and `interval_count`, ie 30 days.
@@ -96,7 +96,7 @@ Changing the renewal schedule of a subscription can be achieved with a PATCH req
}
```
-### Changing Next Renewal Date
+## Changing Next Renewal Date
Changing the next renewal date of a subscription can be achieved through updating the `next_renewal_date` key on the subscription object with a PATCH request to the [subscriptionsPartialUpdate](/docs/admin-api/reference/subscriptions/subscriptionsPartialUpdate) endpoint with your new renewal date and time.
@@ -110,7 +110,7 @@ Changing the next renewal date of a subscription can be achieved through updatin
If you would like to immediately renew the subscription, you can pass a date from the past and the subscription will process a renewal attempt within the next 30 minutes.
-### Triggering a Renewal
+## Triggering a Renewal
To immediately trigger a renewal order for an active subscription, use the [subscriptionsRenewCreate](/docs/admin-api/reference/subscriptions/subscriptionsRenewCreate) endpoint. This creates a new renewal order on demand without waiting for the next scheduled renewal date.
@@ -124,7 +124,7 @@ The endpoint returns the full subscription object with updated renewal details o
The subscription must be in an `active` status to trigger a renewal. For subscriptions in `past_due` status, use the [subscriptionsRetryCreate](/docs/admin-api/reference/subscriptions/subscriptionsRetryCreate) endpoint instead.
-### Identifying Subscription Charges
+## Identifying Subscription Charges
When a `transaction.created` webhook is associated with a subscription, `data.subscription` contains the subscription ID and billing cycle:
@@ -147,11 +147,11 @@ When a `transaction.created` webhook is associated with a subscription, `data.su
The subscription object is empty when the transaction is not associated with a subscription.
-### Updating Payment Details
+## Updating Payment Details
Updating the Payment Gateway of a subscription can done through the [subscriptionsPartialUpdate](/docs/admin-api/reference/subscriptions/subscriptionsPartialUpdate) endpoint.
-**Changing Payment Gateway**
+### Changing Payment Gateway
To change the payment gateway used for bankcard payments of a subscription, send a PATCH request to the [subscriptionsPartialUpdate](/docs/admin-api/reference/subscriptions/subscriptionsPartialUpdate) endpoint with the new `payment_gateway`.
@@ -163,7 +163,7 @@ To change the payment gateway used for bankcard payments of a subscription, send
}
```
-**Updating Bankcard Payment Method**
+### Updating Bankcard Payment Method
To change the bankcard on a subscription, pass a new `card_token` with a PATCH request to the [subscriptionsPartialUpdate](/docs/admin-api/reference/subscriptions/subscriptionsPartialUpdate) endpoint.
@@ -203,7 +203,7 @@ stateDiagram-v2
}
```
-### Retrying Renewal
+## Retrying Renewal
Subscriptions that are `past_due` status can be attempted to retry the renewal, often combined with a new `payment_gateway`, by using the [subscriptionsRetryCreate](/docs/admin-api/reference/subscriptions/subscriptionsRetryCreate) endpoint.
@@ -216,7 +216,7 @@ Subscriptions that are `past_due` status can be attempted to retry the renewal,
The subscription retry endpoint is useful for custom recovery logic when attempting to recover failing subscriptions.
-### Pause
+## Pause
To temporarily stop renewals on an active subscription without cancelling it, use the [subscriptionsPauseCreate](/docs/admin-api/reference/subscriptions/subscriptionsPauseCreate) endpoint. Pausing is useful for win-back flows, customer-requested holds, or pausing a cohort during inventory or fulfillment issues.
@@ -240,7 +240,7 @@ To resume a paused subscription before its `pause_until` date — or to reactiva
}
```
-### Cancel
+## Cancel
To cancel a subscription, use the [subscriptionsCancelCreate](/docs/admin-api/reference/subscriptions/subscriptionsCancelCreate) endpoint to stop all future renewals.
@@ -253,7 +253,7 @@ To cancel a subscription, use the [subscriptionsCancelCreate](/docs/admin-api/re
}
```
-### Bulk Subscription Actions
+## Bulk Subscription Actions
The [`/next-bulk-subscription`](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-subscription) skill in the Next Commerce AI skills repo wraps this workflow — CSV ingestion, dry-run validation, rate limiting, and results reporting for bulk pauses, cancellations, renewal-date shifts, and other subscription updates — for Claude Code, Cursor, and other AI coding agents.
diff --git a/content/docs/admin-api/guides/testing-guide.mdx b/content/docs/admin-api/guides/testing-guide.mdx
index b5215fe..a7091ca 100644
--- a/content/docs/admin-api/guides/testing-guide.mdx
+++ b/content/docs/admin-api/guides/testing-guide.mdx
@@ -13,7 +13,7 @@ Testing your integration is a critical step when developing on the Next Commerce
Cards must be tokenized before submitting on the Admin API, see [iframe card tokenization](/docs/admin-api/guides/payment-methods/bankcard) guide.
-### Test Cards
+## Test Cards
Test cards can be used on live stores and live integrations to create **Test Orders** with the exception they do not touch the gateway and have no attached transactions.
@@ -25,7 +25,7 @@ Test cards can be used on live stores and live integrations to create **Test Ord
Test cards can be used to test your live integration flows without changing any store payment settings. **Test cards are generally safe to use to test your flows.**
-### Test Card Tokens
+## Test Card Tokens
Test card tokens can be used on the API directly without needing to tokenize the card before submitting the create order request.
@@ -37,7 +37,7 @@ Test card tokens can be used on the API directly without needing to tokenize the
Use the test card tokens before you've integrated the [iFrame Card Tokenization](/docs/admin-api/guides/payment-methods/bankcard) to validate your API requests.
-### Test Gateway
+## Test Gateway
The Test Gateway behaves exactly as a regular gateway, when orders are created using the `test` gateway, they also have associated Test transactions.
@@ -47,14 +47,14 @@ The Test Gateway behaves exactly as a regular gateway, when orders are created u
| 5555555555554444 | Any Future Date | Any | Test 3DS payment flow with successful transaction. |
| 4012888888881881 | Any Future Date | Any | Test standard payment declined flow with failed transaction. |
-#### Setup Test Gateway
+### Setup Test Gateway
To setup the test gateway, go to **Settings > Payments > Add Gateway** to add the Test Gateway to your store. Next, add the Test Gateway to your default gateway group or use the gateway ID directly through the Admin API.
The `test` gateway path requires setting up the gateway and can negatively impact your store's live order flows. **Use with caution if your store has live traffic.**
-### Test Subscriptions
+## Test Subscriptions
Subscriptions can be created with both the [Test Gateway](#test-gateway) and [Test Cards](#test-cards), however there are some small behavior differences at this time.
diff --git a/content/docs/admin-api/index.mdx b/content/docs/admin-api/index.mdx
index 7f28afc..316b15b 100644
--- a/content/docs/admin-api/index.mdx
+++ b/content/docs/admin-api/index.mdx
@@ -6,12 +6,12 @@ sidebar_position: 5
---
import { Callout } from 'fumadocs-ui/components/callout';
-### Getting Started
+## Getting Started
At the core of Next Commerce, the Admin API lets developers manage store resources, integrate third-party services, and build seamless external order flows.
-### Authentication
+## Authentication
The Admin API uses the OAuth 2 authorization protocol to manage access to your store's resources. OAuth apps and associated access tokens can be tailored with object-level permissions to ensure that each integrated service only has access to the objects it needs.
@@ -38,11 +38,11 @@ Admin API tokens provide full access to your system, including the ability to pe
**Always keep your Admin API tokens private and secure.**
-### Versioning
+## Versioning
API versioning allows Next Commerce to continuously evolve the platform while maintaining predictable behavior for existing APIs with a path for upgrades and deprecations.
-**Admin API Versions**
+### Admin API Versions
| Version | Status | Docs |
| ---- | ---- | ---- |
@@ -51,14 +51,14 @@ API versioning allows Next Commerce to continuously evolve the platform while ma
| `unstable` | Unstable | [View Reference](/docs/admin-api/reference/unstable/orders/ordersList) |
-**Specify an API Version**
+### Specify an API Version
To specify a version, pass the `X-29next-API-Version` header with your desired API version.
It is **highly recommended** to specify your version on your API requests to ensure consistency for your integration.
-### Rate Limits
+## Rate Limits
Admin APIs are rate-limited to maintain the stability and equity of our platform for all users. We employ a number of methods to enforce rate limits.
diff --git a/content/docs/apps/app-development-flow.mdx b/content/docs/apps/app-development-flow.mdx
index 498ae3b..94cab38 100644
--- a/content/docs/apps/app-development-flow.mdx
+++ b/content/docs/apps/app-development-flow.mdx
@@ -7,7 +7,7 @@ import { Callout } from 'fumadocs-ui/components/callout';
Like any software, Apps require initial development and then ongoing maintenance and improvements. Below is an overview of how to manage develop and release new versions of your app after it's already been installed and live in production.
-### Development Stores
+## Development Stores
App development stores are stores linked to your app for quick iterations, testing and reviewing functionality.
@@ -28,20 +28,20 @@ import DevelopmentStore from '../../_snippets/_offer-development-store.mdx';
-### Releases
+## Releases
Once you're confident with your app and tested it on your development store, you can create a **Release** on the App detail page in your Partner account. Releases are versioned snapshots of your App that can be installed on public stores and also trigger updates for existing installations. Store's always install the latest version of your app.
-#### Versioning
+### Versioning
App versions follow [semantic versioning](https://semver.org/) which allows app developers to create and track releases of their app. App version's should always increase to trigger an available update for stores that have already the app installed.
-#### App Updates
+### App Updates
If store already has your app installed and you create a new release, existing app installations will be able to update to the latest version.
-### Development & Release Flow
+## Development & Release Flow
Below is a diagram to highlight the workflow for creating your first app, reviewing it on your development store, and creating point releases to distribute your app to production stores.
diff --git a/content/docs/apps/app-kit.mdx b/content/docs/apps/app-kit.mdx
index 1e59a3d..11422ce 100644
--- a/content/docs/apps/app-kit.mdx
+++ b/content/docs/apps/app-kit.mdx
@@ -26,10 +26,10 @@ If you already have `python` and `pip`, install with the following command:
pip install next-app-kit
```
-#### Mac OSX Requirements
+### Mac OSX Requirements
See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homebrew-and-Python#python-3x). Once you have completed this step you can install using the `pip` instructions above.
-#### Windows Requirements
+### Windows Requirements
See how to install `python` and `pip` with [Chocolatey](https://python-docs.readthedocs.io/en/latest/starting/install3/win.html). Once you have completed this step you can install using the `pip` instructions above.
## Usage
@@ -43,7 +43,7 @@ With the package installed, you can now use the commands inside your app directo
|`nak push` | push latest app zip file to Next Commerce platform |
-#### Setup
+### Setup
Configures the current directory with necessary data to push the app files to Next Commerce.
**Data collected by the `setup` command:**
@@ -52,8 +52,8 @@ Configures the current directory with necessary data to push the app files to Ne
- **Email** - your email used to access your partner account.
- **Password** - your password used to access your partner account.
-#### Build
+### Build
Creates a new version (zip of the current directory files) to prepare your app to be pushed to Next Commerce.
-#### Push
+### Push
Pushes the latest version to Next Commerce and to your development stores to review and test your app.
diff --git a/content/docs/apps/assets.mdx b/content/docs/apps/assets.mdx
index 6af80d3..901bdc1 100644
--- a/content/docs/apps/assets.mdx
+++ b/content/docs/apps/assets.mdx
@@ -16,7 +16,7 @@ App Assets ship inside your App bundle. They are separate from a store's media l
**App bundle max size is 2MB**, it's important to minimize and reduce the size of the assets in your App to maintain efficiency. If you are compiling CSS or JS bundles locally, it is recommended to not include the raw source files and only include the compiled minified files.
-### Asset Usage Example
+## Asset Usage Example
import AppUsageExample from '../../_snippets/_app-usage-example.mdx';
@@ -25,7 +25,7 @@ import AppUsageExample from '../../_snippets/_app-usage-example.mdx';
-### Supported File Types
+## Supported File Types
| File Extension |
|-----|
diff --git a/content/docs/apps/event-tracking.mdx b/content/docs/apps/event-tracking.mdx
index 871222f..603d515 100644
--- a/content/docs/apps/event-tracking.mdx
+++ b/content/docs/apps/event-tracking.mdx
@@ -13,7 +13,7 @@ An installed event tracker simplifies the setup flow and makes the app easier fo
Event trackers and App snippets are not cross compatible as Event Trackers are loaded in their own sandboxed environment for greater security.
-### Add Event Tracker to Manifest
+## Add Event Tracker to Manifest
When building your app, map a javascript file to be installed as an [Event Tracker](/docs/storefront/event-tracking).
@@ -41,7 +41,7 @@ When building your app, map a javascript file to be installed as an [Event Track
When your app is installed, an event tracker will be automatically created with the contents of the JavaScript file mapped to the `storefront_event_tracker` key in your manifest.json.
-### Access App Settings Inside Event Tracker
+## Access App Settings Inside Event Tracker
Apps also have [Settings](/docs/apps/settings) that can be used to control how the app works, such as enabling or disabling functionality or adding an ID for the tracking script.
diff --git a/content/docs/apps/guides/dispute-service.mdx b/content/docs/apps/guides/dispute-service.mdx
index 55b7ed2..ef2afc9 100644
--- a/content/docs/apps/guides/dispute-service.mdx
+++ b/content/docs/apps/guides/dispute-service.mdx
@@ -94,7 +94,7 @@ For RDR alerts, the refund is already processed by the gateway. Your app should
-### Step 8 - Cancel Order / Cancel Fulfillment
+### Step 8 - Cancel Order / Cancel Fulfillment
If the order is not yet fulfilled, it may be ideal to cancel the order or cancel fulfillment to stop the order from being shipped to the customer. See [Canceling Fulfillment](#canceling-fulfillment) detail below.
@@ -213,7 +213,7 @@ Setting `is_external: true` on a refund will create the refund without attemptin
## Dispute Resolutions
-**Alert Resolutions**
+### Alert Resolutions
- `could_not_find_order` - You could not match the alert to an order or transaction.
- `declined_or_canceled_nothing_to_do` - Customer had declined or canceled the order; no further action is necessary.
diff --git a/content/docs/apps/index.mdx b/content/docs/apps/index.mdx
index 07fc105..3d71a2b 100644
--- a/content/docs/apps/index.mdx
+++ b/content/docs/apps/index.mdx
@@ -11,16 +11,16 @@ Apps and supporting tools are in Public Beta. If you have questions or run into
Apps let you extend built-in functionality of the Next Commerce platform to solve merchant challenges and ship new functionality as an easily installed app.
-### Apps Allow You To
+## Apps Allow You To
-#### Extend Core Functionality
+### Extend Core Functionality
Use [Webhooks](/docs/webhooks) to subscribe to events and the [Admin API](/docs/admin-api) to add new logic and integrations, see the [Server to Server Guide](/docs/apps/guides/server-to-server-apps).
-#### Extend Storefront Themes
+### Extend Storefront Themes
Use [Event Tracking](/docs/apps/event-tracking) or [App Snippets](https://developers.nextcommerce.com/docs/apps/snippets) to extend storefront themes, see the [Storefront Extension Guide](/docs/apps/guides/storefront-extension).
-### Example Apps
+## Example Apps
We have full-featured, open-source example apps that provide complete code examples for many of the concepts needed to build apps.
@@ -37,7 +37,7 @@ import DevelopmentStore from '../../_snippets/_offer-development-store.mdx';
-### App Developer Reference Guides
+## App Developer Reference Guides
To upload your snippets and manifest.json, install [App Kit](/docs/apps/app-kit) to zip your snippet files and push them to Next Commerce.
-## Manifest Reference
+## Example manifest.json
The manifest.json file is used to configure your app.
```json title="Example manifest.json"
diff --git a/content/docs/apps/oauth/getting-started.mdx b/content/docs/apps/oauth/getting-started.mdx
index b4fa866..7d148a4 100644
--- a/content/docs/apps/oauth/getting-started.mdx
+++ b/content/docs/apps/oauth/getting-started.mdx
@@ -7,11 +7,11 @@ import { Callout } from 'fumadocs-ui/components/callout';
Server-side Apps that use Stores' Admin API must obtain authorization using OAuth 2.0 ([see overview](/docs/apps/oauth)). This guide shows you how to authorize your app and retrieve your Access Token to access the Admin API.
-### Step 1: Retrieve API Credentials
+## Step 1: Retrieve API Credentials
To get started, make sure that you have your Apps' `client_id` and `client_secret` available on the App details in your Partner account.
-### Step 2: App Permissions Setup
+## Step 2: App Permissions Setup
During the App installation flow, Apps that have `oauth` configured will be redirected to the OAuth App URL from the App Settings.
@@ -35,7 +35,7 @@ https://{network_domain}/oauth2/authorize/?response_type=code&client_id={client_
|`scope`| A space separated list of scopes such as `orders:read orders:write users:read users:write`. [See list of all available scopes](/docs/admin-api/permissions). |
-### Step 3: Confirm Installation
+## Step 3: Confirm Installation
After user click's Authorize to confirm App installation, it will redirect to the `redirect_uri` with `?store={network_domain}&code={authorize_code}` appended.
@@ -48,7 +48,7 @@ https://yourapp.com/setup/authorize/?store={network_domain}&code={authorization_
|`network_domain`| The store network domain that is installing the app. Can be referenced from the `store` url parameter sent to your app OAuth Redirect URL. |
|`authorization_code`| The authorization code used to retrieve the Access Token in the next step. |
-### Step 4: Retrieve Access Token
+## Step 4: Retrieve Access Token
After you have the `authorization_code`, you then need to retrieve the access token to gain access to the Admin API.
diff --git a/content/docs/apps/oauth/index.mdx b/content/docs/apps/oauth/index.mdx
index 82872c9..b3f60bb 100644
--- a/content/docs/apps/oauth/index.mdx
+++ b/content/docs/apps/oauth/index.mdx
@@ -6,21 +6,21 @@ sidebar_position: 2
This guide introduces OAuth Authentication for Server-side Apps to access the Admin API.
-### Introduction to OAuth
+## Introduction to OAuth
OAuth 2.0 is the industry standard protocol for authorizing and assigning permissions to 3rd party apps. There are many great guides on the internet regarding OAuth 2.0, such as this [OAuth 2.0 introduction guide from Auth0.com](https://auth0.com/intro-to-iam/what-is-oauth-2/). Your Server-side App's language most likely has pre-built packages to assist with handling OAuth 2.0 Authentication flows.
-### Access Tokens
+## Access Tokens
OAuth 2.0 uses **Access Tokens** which represent authorization to access resources on behalf of the end-user, ie access the Admin API. During the setup flow for your app, you'll be able to obtain request required permissions, get authorization from a user and retrieve a long lived access token to use for all future access to the Admin API.
-### OAuth Setup Flow
+## OAuth Setup Flow
Next Commerce uses OAuth 2.0's Authorization Code Flow to issue an access token on behalf of users.
-##### Authorization Flow
+### Authorization Flow
``` mermaid
sequenceDiagram
@@ -35,7 +35,7 @@ sequenceDiagram
App->>Store: App can now access Admin API with Access Token
```
-##### Authorization Flow Step Detail
+### Authorization Flow Step Detail
1. User initiates the App installation process.
2. Store redirects to the App URL configured in App OAuth Settings.
@@ -47,6 +47,6 @@ sequenceDiagram
8. The app can now access the Admin API using the Access Token, [see Admin API examples](/docs/admin-api).
-### OAuth Guides
+## OAuth Guides
diff --git a/content/docs/apps/oauth/install-flows.md b/content/docs/apps/oauth/install-flows.md
index 37b5720..4ba778e 100644
--- a/content/docs/apps/oauth/install-flows.md
+++ b/content/docs/apps/oauth/install-flows.md
@@ -5,7 +5,7 @@ sidebar_position: 6
---
-### Private Apps
+## Private Apps
All apps start in a `private` state while the app developer is building and testing their app internally. While an app is `private`, you can use the "Install Link" builder form on your app detail page.
You may also want to trigger the install flow from your app's UI, to do this you can add a form to build the install link for your user to start the install flow on their store.
@@ -20,7 +20,7 @@ https://{store_subdomain}.29next.store/dashboard/apps/install-app/?client_id={cl
|`client_id`| Your app Client ID found on the app detail page. |
-### Public Apps
+## Public Apps
Public apps show in all store dashboards and can be installed by any merchant at any time. If you plan to publish your app, ensure your app handles the install flow with a good user experience that guides the user through the process with your app.
diff --git a/content/docs/apps/oauth/session-auth.mdx b/content/docs/apps/oauth/session-auth.mdx
index a7552a1..d560bb7 100644
--- a/content/docs/apps/oauth/session-auth.mdx
+++ b/content/docs/apps/oauth/session-auth.mdx
@@ -7,7 +7,7 @@ import { Callout } from 'fumadocs-ui/components/callout';
Session tokens are a method your app can use to authenticate users and requests from Next Commerce and your App.
-### How Session Tokens Work
+## How Session Tokens Work
Session tokens follow the [JSON Web Tokens](https://jwt.io/introduction) standard. JWT tokens are signed objects your app can use to authenticate users to your app, see the example decoded token below. The JWT token is appended to requests to your app in the `token` parameter.
@@ -41,11 +41,11 @@ print(token)
Tokens include details of the store and the store user (id & email) making the request. A valid token can be trusted as a verified request from a store with your app installed.
-### Token Expiration
+## Token Expiration
Tokens are shortlived with an expiration of 30 seconds, meaning they quickly expire and cannot be reused. It is recommended that you authenticate the users into your App with every request.
-### Session Token Flow
+## Session Token Flow
Session tokens are generated from the store dashboard and can be used by your App to verify request authenticity before authenticating the user to your app.
diff --git a/content/docs/apps/review.mdx b/content/docs/apps/review.mdx
index 221eb28..295299e 100644
--- a/content/docs/apps/review.mdx
+++ b/content/docs/apps/review.mdx
@@ -12,7 +12,7 @@ Congratulations, you've built an app and now it's ready to publish to all Next C
Private apps can be shared with merchants and installed using the **Install Link** feature available on your app dashboard. Use install links to install and validate your app with merchants before submitting for review.
-### App Review Checklist
+## App Review Checklist
- Your app is currently live and on more than 3 merchant stores.
- You've uploaded a logo to your app that is properly sized and displays nicely.
@@ -24,7 +24,7 @@ Private apps can be shared with merchants and installed using the **Install Link
- Your app subscribes to the [`app.uninstalled` webhook event](/docs/webhooks#webhook-events) for handling uninstall clean up on your end.
-### Submit App for Review
+## Submit App for Review
Once you've completed all of your app functionality and the checklist items, you're now ready to submit your app for review. Use the link below to submit your app for review.
diff --git a/content/docs/apps/settings.mdx b/content/docs/apps/settings.mdx
index e0cf273..1436758 100644
--- a/content/docs/apps/settings.mdx
+++ b/content/docs/apps/settings.mdx
@@ -15,7 +15,7 @@ import GoogleAnalytics from '../../_snippets/_view-google-analytics.mdx';
-### Example Usage
+## Example Usage
At this time, the primary use case of settings is to allow apps to store settings data that can then be used with snippets. This makes it possible to extend storefront theme's natively through the use of that are rendered in themes yet fully contained and controlled by your app. :tada:
@@ -54,7 +54,7 @@ if (app.settings.custom_app_id_enabled) {
For Sever to Server Apps with access to the Admin API, you can update the app settings values stored in the database on the Admin API allowing you to configure the app from your external application.
-### Reference
+## Reference
| Attribute | Required | Description |
| -----------| --------------------|---------------- |
@@ -70,11 +70,11 @@ For Sever to Server Apps with access to the Admin API, you can update the app se
|`min_value`| No | Applicable to number field types to set a min value. |
-### Input Types
+## Input Types
Settings schema input types map to input fields that will be rendered in the theme settings form in the dashboard.
-#### text
+### text
```json title="text"
{
@@ -89,7 +89,7 @@ Settings schema input types map to input fields that will be rendered in the the
```
-#### textarea
+### textarea
```json title="textarea"
{
@@ -101,7 +101,7 @@ Settings schema input types map to input fields that will be rendered in the the
}
```
-#### checkbox
+### checkbox
```json title="checkbox"
{
@@ -112,7 +112,7 @@ Settings schema input types map to input fields that will be rendered in the the
"default": true
}
```
-#### number
+### number
```json title="number"
{
"type": "number",
@@ -126,7 +126,7 @@ Settings schema input types map to input fields that will be rendered in the the
```
-#### email
+### email
```json title="email"
{
@@ -138,7 +138,7 @@ Settings schema input types map to input fields that will be rendered in the the
}
```
-#### radio
+### radio
```json title="radio"
{
@@ -160,7 +160,7 @@ Settings schema input types map to input fields that will be rendered in the the
}
```
-#### select
+### select
```json title="select"
{
"type": "select",
@@ -185,7 +185,7 @@ Settings schema input types map to input fields that will be rendered in the the
}
```
-#### multi-select
+### multi-select
```json title="multi-select"
{
"type": "select",
@@ -210,7 +210,7 @@ Settings schema input types map to input fields that will be rendered in the the
}
```
-#### url
+### url
```json title="url"
{
"type": "url",
@@ -222,7 +222,7 @@ Settings schema input types map to input fields that will be rendered in the the
```
-#### color
+### color
```json title="color"
{
"type": "color",
diff --git a/content/docs/apps/snippets.mdx b/content/docs/apps/snippets.mdx
index cca94f2..f7113c9 100644
--- a/content/docs/apps/snippets.mdx
+++ b/content/docs/apps/snippets.mdx
@@ -16,7 +16,7 @@ import GoogleTagManager from '../../_snippets/_view-google-tag-manager.mdx';
-### Locations
+## Locations
Theme's on the Next Commerce platform support `app_hooks` which are locations within storefront themes your app can target to include your snippets without needing the customize the theme itself.
@@ -30,7 +30,7 @@ import AppHookLocations from '../../_snippets/_app-hook-locations.mdx';
-### Snippet Usage Example
+## Snippet Usage Example
import AppUsageExample from '../../_snippets/_app-usage-example.mdx';
diff --git a/content/docs/campaigns/index.mdx b/content/docs/campaigns/index.mdx
index 94b0834..aaed8ce 100644
--- a/content/docs/campaigns/index.mdx
+++ b/content/docs/campaigns/index.mdx
@@ -104,7 +104,7 @@ Pick one at the `campaign-init` template prompt. Each template ships with SDK-re
-[**See all available templates →**](/docs/campaigns/templates)
+[See all available templates →](/docs/campaigns/templates)
## Campaign Flow
@@ -274,7 +274,7 @@ Two mechanisms skip tracking entirely — including the always-on internal `next
### Event reference
-- [**Analytics events**](https://cart-sdk.nextcommerce.com/latest/reference/analytics-events/) — every `dl_*` event the SDK emits, which ones fire automatically, and what each provider receives
+- [Analytics events](https://cart-sdk.nextcommerce.com/latest/reference/analytics-events/) — every `dl_*` event the SDK emits, which ones fire automatically, and what each provider receives
---
diff --git a/content/docs/index.mdx b/content/docs/index.mdx
index f886044..5524e82 100644
--- a/content/docs/index.mdx
+++ b/content/docs/index.mdx
@@ -54,11 +54,11 @@ Campaigns and storefronts are the customer-facing layer — both produce orders
-Already decided to start a new Campaign Page Kit project? The [**Campaign agent quickstart**](/docs/agent-setup) gives your coding agent a thin wrapper around the current CLI while preserving your template, route, and project choices. For reusable guidance across platform tasks, use [**Next Commerce AI Skills**](/docs/skills).
+Already decided to start a new Campaign Page Kit project? The [Campaign agent quickstart](/docs/agent-setup) gives your coding agent a thin wrapper around the current CLI while preserving your template, route, and project choices. For reusable guidance across platform tasks, use [Next Commerce AI Skills](/docs/skills).
-Before you ship, run your flows through [**Testing**](/docs/testing) — safe QA on a live store with no real charges.
+Before you ship, run your flows through [Testing](/docs/testing) — safe QA on a live store with no real charges.
diff --git a/content/docs/skills/index.mdx b/content/docs/skills/index.mdx
index c158d17..207b89b 100644
--- a/content/docs/skills/index.mdx
+++ b/content/docs/skills/index.mdx
@@ -4,7 +4,7 @@ description: Pre-built skills that give AI coding agents deep knowledge of the N
---
import { Callout } from 'fumadocs-ui/components/callout';
-[**Next Commerce AI Skills**](https://github.com/NextCommerceCo/skills) are pre-built skills that give AI coding agents deep knowledge of the Next Commerce platform — APIs, CLI workflows, and architecture patterns — so they can work autonomously on your store.
+[Next Commerce AI Skills](https://github.com/NextCommerceCo/skills) are pre-built skills that give AI coding agents deep knowledge of the Next Commerce platform — APIs, CLI workflows, and architecture patterns — so they can work autonomously on your store.
Skills are structured markdown files. Any AI tool that accepts a context file or system prompt can use them — Claude Code, OpenAI Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, and 50+ other LLM-powered agents.
@@ -12,69 +12,81 @@ For an optional quickstart that follows the current Campaign Page Kit CLI withou
## Install
-The simplest path is the [`skills` CLI](https://github.com/vercel-labs/skills) — it pulls `SKILL.md` files from a GitHub repo and drops them into the right config directory for whichever assistant you use. The target agent is auto-detected by default.
+The [`skills` CLI](https://github.com/vercel-labs/skills) is the quickest path: it pulls each skill from GitHub and installs it into the skill directory of the AI tool it detects.
```bash
-# Install every skill from this repo
-npx skills add NextCommerceCo/skills
+# Install every skill for your detected agent
+npx skills add NextCommerceCo/skills -g
# Install one skill
-npx skills add NextCommerceCo/skills -s next-theme-dev
+npx skills add NextCommerceCo/skills -g --skill next-ops-scan
-# List skills without installing
-npx skills add NextCommerceCo/skills --list
-
-# Target a specific agent (auto-detected by default)
-npx skills add NextCommerceCo/skills -a claude-code
+# Target a specific agent
+npx skills add NextCommerceCo/skills -g -a codex
```
-Once installed, Claude Code auto-detects when a skill is relevant, or you can invoke it directly with `/` (e.g. `/next-theme-dev`). If the skills directory didn't exist before Claude Code started, restart it so it can discover the new directory.
+To manage versions from a checkout, clone the repository and run its guided installer. It previews every change before writing, and installs into Claude Code (`~/.claude/skills`), Codex (`~/.codex/skills`), or `~/.agents/skills`.
```bash
-# Update every installed skill
-npx skills update
-
-# Update one skill
-npx skills update next-theme-dev
+git clone https://github.com/NextCommerceCo/skills.git
+cd skills
+./skills.sh
```
+Restart your agent session after installing so it loads the new skills. Then ask for the work in plain language, or invoke a skill directly with `/` in Claude Code (for example `/next-ops-scan`).
+
-For agents the `skills` CLI doesn't support, each `SKILL.md` is plain markdown — load it as a system prompt, context file, or chat upload.
+For agents without a native skill directory, each `SKILL.md` is plain markdown: load it as a system prompt, context file, rule, or chat upload.
### Ask your AI tool to install
-You can also let your AI tool drive the install — it knows where files live for the current OS and assistant:
+You can also let your AI tool drive the install. It knows where files live for your operating system and assistant:
```text
Install the Next Commerce AI skill I need from https://github.com/NextCommerceCo/skills.
-Use the installation location for my current AI tool and operating system. If my tool
-supports native skills, install each skill as a directory containing its SKILL.md.
-If it only supports rules, prompts, or context files, add the relevant SKILL.md there.
-Prefer HTTPS clone unless my GitHub SSH access is already configured.
+Prefer cloning the repo and running ./skills.sh, choosing the installation location for my
+current AI tool. If a local checkout is not appropriate, use the public npx skills installer
+or load the relevant SKILL.md as context.
```
Tell it which skill you want, or ask it to inspect [`skills.json`](https://github.com/NextCommerceCo/skills/blob/main/skills.json) and choose the relevant one.
+### Keep skills up to date
+
+An installed skill is a copy, so it doesn't change when the repository does. Check before starting work that depends on one:
+
+- **With a checkout:** run `git pull --ff-only`, then `./skills.sh status` to mark older copies `stale`, and `./skills.sh install ` to replace them.
+- **With the `skills` CLI:** run `npx skills update`.
+- **Without either:** compare the `version:` line in your installed `SKILL.md` with that skill's `version` in [`skills.json`](https://github.com/NextCommerceCo/skills/blob/main/skills.json).
+
+`next-campaigns-create` checks for a newer version itself each time it runs. Restart the agent session after any update.
+
## Available skills
| Skill | What it does | When to use it |
| --- | --- | --- |
-| [**next-theme-figma**](https://github.com/NextCommerceCo/skills/tree/main/next-theme-figma) | Prepare Figma storefront designs for Spark theme implementation — validates source structure, classifies sections and assets, records Spark divergences, and generates a low-inference handoff for `next-theme-dev` | You have a Figma storefront design (PDP, homepage, etc.) you want to turn into a Next Commerce theme |
-| [**next-theme-dev**](https://github.com/NextCommerceCo/skills/tree/main/next-theme-dev) | Build and customize storefront themes — DTL templates, ntk CLI, Tailwind CSS, settings, side cart | You're editing theme files, setting up a new storefront, or debugging template issues |
-| [**next-campaigns-create**](https://github.com/NextCommerceCo/skills/tree/main/next-campaigns-create) | Provision a launch-ready Campaigns App campaign over the Admin API — reads the store's catalogue, gateways, and shipping methods, recommends a structure, then creates the campaign, packages, shipping methods, and tier/voucher offers behind an approval gate; hands back the campaign `api_key` and package IDs | A new campaign needs to exist on a store before funnel work starts — creates new campaigns only, it can't edit an existing one |
-| [**next-campaigns-setup**](https://github.com/NextCommerceCo/skills/tree/main/next-campaigns-setup) | End-to-end CPK campaign setup — scaffolds the project, copies a starter template, seeds `campaigns.json`, wires up the API key, store details, and analytics in one pass | Starting a new CPK campaign for a brand — after the campaign exists in the Campaigns App |
-| [**next-bulk-fulfill**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-fulfill) | Update orders to **Fulfilled** with tracking numbers from a CSV | A fulfillment provider shipped orders but tracking didn't sync back — orders stuck in *Processing* |
-| [**next-bulk-move**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-move) | Move fulfillment orders between warehouse locations in bulk — by order-number file or by Product ID / SKU list | Switching fulfillment providers, or moving every FO containing a given SKU/product to a new location |
-| [**next-bulk-subscription**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-subscription) | Apply official actions (pause, cancel) or a PATCH (renewal date, interval, gateway, address) to a list of subscription IDs | Merchant wants to bulk-pause, bulk-shift renewals, bulk-cancel, or migrate subscriptions between gateways |
-| [**next-ops-scan**](https://github.com/NextCommerceCo/skills/tree/main/next-ops-scan) | Read-only daily operations risk scan for a store — surfaces Incomplete orders, Rejected orders, and delivery-tracking failures or stale shipments with manual next steps | You want a routine health check to catch risky orders and reduce disputes |
+| [**next-theme-figma**](https://github.com/NextCommerceCo/skills/tree/main/next-theme-figma) | Turn a Figma storefront design into a validated, low-inference handoff package for `next-theme-dev`: sections, assets, geometry, copy, and design tokens | You have a Figma storefront design (PDP, homepage, and so on) to build as a Next Commerce theme |
+| [**next-theme-design**](https://github.com/NextCommerceCo/skills/tree/main/next-theme-design) | Turn a live website or its HTML into a validated handoff package for `next-theme-dev`: captures at three widths, sections, geometry, copy decisions, styles, behaviors, and commerce divergences | You want an existing page, such as a merchant's landing page, rebuilt as a Next Commerce storefront |
+| [**next-theme-dev**](https://github.com/NextCommerceCo/skills/tree/main/next-theme-dev) | Build, modify, and debug storefront themes: Spark, Intro Bootstrap, Theme Settings, the `ntk` CLI, DTL templates, storefront GraphQL, and builds from Figma or live-site handoff packages | You're editing theme files, setting up a new storefront, building from a handoff package, or debugging templates |
+| [**next-campaigns-create**](https://github.com/NextCommerceCo/skills/tree/main/next-campaigns-create) | Create a launch-ready Campaigns App campaign over the Admin API: packages, shipping, quantity Buy 1/2/3, buy-X-get-Y as a labeled percentage, and gift-with-purchase, behind a plan-hash approval gate. Hands back the campaign `api_key` and package IDs | A new campaign needs to exist on a store before funnel work starts. It creates new campaigns only |
+| [**next-campaigns-setup**](https://github.com/NextCommerceCo/skills/tree/main/next-campaigns-setup) | Scaffold and configure a new Campaign Page Kit campaign end to end: project, starter template, config, and analytics | Starting a new CPK campaign after the campaign exists in the Campaigns App |
+| [**next-bulk-fulfill**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-fulfill) | Mark orders **Fulfilled** with tracking numbers from a CSV when a fulfillment provider's sync-back fails | A provider shipped orders but tracking didn't sync back, leaving orders stuck in *Processing* |
+| [**next-bulk-move**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-move) | Move fulfillment orders between warehouse locations in bulk, from a file of order numbers or a product/SKU list | Switching fulfillment providers, or moving every fulfillment order containing a given SKU or product |
+| [**next-bulk-subscription**](https://github.com/NextCommerceCo/skills/tree/main/next-bulk-subscription) | Pause, cancel, or update subscriptions in bulk from a CSV or XLSX of subscription IDs, with a dry run and verification | Bulk-pausing, shifting renewal dates, changing intervals or gateways, or cancelling a list of subscriptions |
+| [**next-ops-scan**](https://github.com/NextCommerceCo/skills/tree/main/next-ops-scan) | Read-only daily risk scan for one store: Incomplete and Rejected orders, delivery-tracking failures, and stale shipments | A routine health check to catch risky orders and reduce disputes |
+
+For design-led theme work, run `next-theme-figma` (Figma source) or `next-theme-design` (live page source) before `next-theme-dev`. The three theme skills are installed together.
## Prerequisites
-Each skill lists its own requirements in its `SKILL.md`. Common across all skills:
+Each skill lists its own requirements in its `SKILL.md` and `README.md`. In general:
+
+- **Operations and campaign provisioning skills** (`next-bulk-*`, `next-ops-scan`, `next-campaigns-create`) run Python 3 scripts that use only the standard library. They need an Admin API token with the scopes the skill names, in a local `.env` as `{SUBDOMAIN}_NEXT_ADMIN_API_TOKEN` or in the environment. Create the API access under **Settings → API Access**.
+- **Theme skills** need Python 3.10 or newer (`next-theme-figma` also uses Node.js), a browser tool that can take screenshots, and for `next-theme-dev` a Storefront OAuth app API key with `themes:read` and `themes:write`.
+- **`next-campaigns-setup`** needs Node.js and npm, a Campaign Page Kit project, and the campaign's Campaign Cart API key.
-- Access to a Next Commerce store
-- An API key with the scopes specified by the skill (create at **Dashboard → Settings → API Access**)
+Skills that change store data (bulk actions, campaign creation, theme pushes) show a plan or dry run and wait for your approval before writing.
## Machine-readable index
diff --git a/content/docs/storefront/checkout-links.mdx b/content/docs/storefront/checkout-links.mdx
index 29f11f7..6542fc1 100644
--- a/content/docs/storefront/checkout-links.mdx
+++ b/content/docs/storefront/checkout-links.mdx
@@ -5,16 +5,16 @@ description: URL parameters for pre-loading a store's checkout with products, vo
Checkout Links allow you add links from any website, email or web marketing channel directly to your store's checkout flow with items pre-loaded in their cart.
-### Example Checkout Links
+## Example Checkout Links
-#### As a one-time purchase
+### As a one-time purchase
With the link below, 2 products would be added to the cart with an applied voucher.
```bash title="One-Time Purchase"
https://{domain}/checkout/add/?product=12:1&product=13:3&voucher=PROMO¤cy=usd
```
-#### As a subscription
+### As a subscription
With the following link, 1 product would be added to the cart as a subscription renewing every 3 months.
@@ -23,11 +23,11 @@ https://{domain}/checkout/add/?product=12:1:3:month¤cy=usd
```
-### Supported Parameters
+## Supported Parameters
Checkout link parameters can be broadly split into two groups, [Cart Parameters](#cart-parameters) controlling the products and discounts applied to the cart and [Attribution Parameters](#attribution-parameters) to marketing attribution reporting.
-#### Cart Parameters
+### Cart Parameters
| Parameter | Values | Description |
| -----------| -------- |--------------------|
@@ -37,7 +37,7 @@ Checkout link parameters can be broadly split into two groups, [Cart Parameters]
| `replace` | true/false | replace existing cart, default is true |
-#### Attribution Parameters
+### Attribution Parameters
In addition to populating the cart, you can pass attribution parameters to attribute the order to your marketing channel.
| Parameter | Description |
diff --git a/content/docs/storefront/index.md b/content/docs/storefront/index.md
index ae90cf3..cf63904 100644
--- a/content/docs/storefront/index.md
+++ b/content/docs/storefront/index.md
@@ -5,7 +5,7 @@ description: "Overview of the storefront developer tools: themes, event tracking
The Next Commerce storefront is a flexible, customizable front-end layer for your ecommerce business. Whether you're building a completely custom storefront or enhancing an existing theme, this section will guide you through the tools and features available to developers.
-### Themes
+## Themes
Themes allow you to fully control the look and feel of your storefront using modern front-end technologies. Each theme includes layouts, templates, stylesheets, and scripts, giving you full creative freedom to build a branded customer experience.
@@ -16,7 +16,7 @@ Themes allow you to fully control the look and feel of your storefront using mod
Learn how to [build and manage your theme →](/docs/storefront/themes)
-### Event Tracking
+## Event Tracking
Capture user behavior, conversion events, and key storefront interactions with built-in event tracking tools.
@@ -27,7 +27,7 @@ Capture user behavior, conversion events, and key storefront interactions with b
Learn how to [implement tracking for your storefront →](/docs/storefront/event-tracking)
-### Storefront GraphQL API
+## Storefront GraphQL API
Power deeper customizations, dynamic content loading, and headless experiences using our Storefront GraphQL API.
diff --git a/content/docs/storefront/themes/cdn-and-caching.mdx b/content/docs/storefront/themes/cdn-and-caching.mdx
index 5032828..edb0d43 100644
--- a/content/docs/storefront/themes/cdn-and-caching.mdx
+++ b/content/docs/storefront/themes/cdn-and-caching.mdx
@@ -11,14 +11,14 @@ Storefront leverages CDNs and many caching strategies to ensure fast performant
Always use the store network domain `https://{store}.29next.store` when developing, previewing, debugging, and verifying themes. Do not use a mapped public storefront domain to decide whether a theme change landed.
-### Asset CDN
+## Asset CDN
All merchant uploaded media assets and theme assets are loaded from our CDN for the fastest performance.
- **Media** - Links to uploaded media should always use the `cdn.29next.store`
- **Theme Assets** - Theme assets should use the [asset_url](/docs/storefront/themes/templates/filters#asset_url) in templates which always generates a full CDN link on the storefront.
-### Full Page Caching
+## Full Page Caching
All pages on storefront are cached for 5 minutes to ensure popular pages are as fast as possible for customers and minimal impact on the overall platform load.
@@ -30,7 +30,7 @@ All pages on storefront are cached for 5 minutes to ensure popular pages are as
Confirm the latest theme on `https://{store}.29next.store` first. After it is correct there, check the mapped public storefront domain as a final customer-path smoke test.
-### Template Caching
+## Template Caching
Themes use many templates ie `layouts`, `partials`, and `assets` that when compiled together create amazing customer experiences. Templates are cached in memory to reduce database queries when compiling templates into the full html response.
diff --git a/content/docs/storefront/themes/guides/custom-page-templates.mdx b/content/docs/storefront/themes/guides/custom-page-templates.mdx
index 4f4639c..a22d270 100644
--- a/content/docs/storefront/themes/guides/custom-page-templates.mdx
+++ b/content/docs/storefront/themes/guides/custom-page-templates.mdx
@@ -9,7 +9,7 @@ import { Callout } from 'fumadocs-ui/components/callout';
Pages created in the storefront dashboard (**Storefront > Pages**) can have very diverse design requirements that often require custom layouts. In this guide, we'll go over some of the best practices for creating and managing custom page templates.
-### Page Templates Location
+## Page Templates Location
In the `templates/pages` directory of a theme, theme developers can edit/manage the custom page templates.
@@ -20,9 +20,9 @@ pages
└── page..html
```
-### Extend & Override
+## Extend & Override
-**Create a Custom Page Template**
+### Create a Custom Page Template
Create a new page template in the `templates/pages` directory with the following naming convention:
@@ -33,7 +33,7 @@ templates/pages/page..html
Templates that follow this naming convention will be selectable from the page detail area in the storefront dashboard.
-**Extend & Override Default Page Template**
+### Extend & Override Default Page Template
As a best practice, you should [extend](/docs/storefront/themes/templates/tags#extends--block) the default page template to override the necessary [template blocks](/docs/storefront/themes/templates/tags#extends--block) to achieve your customization with a limited amount of duplicate code.
@@ -47,7 +47,7 @@ As a best practice, you should [extend](/docs/storefront/themes/templates/tags#e
```
This strategy will simplify the creation and management of custom page templates so you can focus on the customized areas for the new custom product template.
-**Select Template for Page**
+### Select Template for Page
On your page of choice, select your newly created template as the **Theme Template** to activate the template for your page in the storefront.
diff --git a/content/docs/storefront/themes/guides/custom-product-templates.mdx b/content/docs/storefront/themes/guides/custom-product-templates.mdx
index dec400e..f506c47 100644
--- a/content/docs/storefront/themes/guides/custom-product-templates.mdx
+++ b/content/docs/storefront/themes/guides/custom-product-templates.mdx
@@ -9,7 +9,7 @@ import { Callout } from 'fumadocs-ui/components/callout';
Products can have very diverse design requirements that often require custom layouts. In this guide, we'll go over some of the best practices for creating and managing custom product templates.
-### Product Templates Location
+## Product Templates Location
In the `templates/catalogue` directory of a theme, theme developers can edit/manage the product page templates.
@@ -20,9 +20,9 @@ catalogue
└── product..html
```
-### Extend & Override
+## Extend & Override
-**Create a Custom Product Template**
+### Create a Custom Product Template
Create a new product template in the **templates>catalogue** directory with the following naming convention:
@@ -33,7 +33,7 @@ templates/catalogue/product..html
Templates that follow this naming convention will be selectable on the product detail to use on the storefront.
-**Extend & Override Default Product Template**
+### Extend & Override Default Product Template
As a best practice, you should [extend](/docs/storefront/themes/templates/tags#extends--block) the default product template to override the necessary [template blocks](/docs/storefront/themes/templates/tags#extends--block) to achieve your customization with a limited amount of duplicate code.
@@ -56,7 +56,7 @@ As a best practice, you should [extend](/docs/storefront/themes/templates/tags#e
This strategy will simplify the creation and management of custom product templates so you can focus on the customized areas for the new custom product template.
-**Select Template for Product**
+### Select Template for Product
On your product of choice, select your newly created template as the Product Template to activate the template on your product in the storefront.
diff --git a/content/docs/storefront/themes/guides/personalized-products.mdx b/content/docs/storefront/themes/guides/personalized-products.mdx
index 89bcd57..b1dc4f5 100644
--- a/content/docs/storefront/themes/guides/personalized-products.mdx
+++ b/content/docs/storefront/themes/guides/personalized-products.mdx
@@ -15,7 +15,7 @@ Some products need customer input at the time of purchase — an engraving on a
-### Add Property Inputs to the Product Template
+## Add Property Inputs to the Product Template
Property inputs are named `properties[]`, where `` is the label stored with the line. Add them inside the [add-to-cart form](/docs/storefront/themes/templates/tags#cart_form) alongside the fields generated by the `cart_form` tag.
@@ -43,7 +43,7 @@ Add one input per property. A mug with an engraving and a font choice uses `prop
-### Display Properties in the Cart
+## Display Properties in the Cart
The cart template receives a `formset` of cart line forms. Each `form.instance` is a [line](/docs/storefront/themes/templates/objects#line) with a `properties` list of `key` and `value` pairs.
@@ -71,7 +71,7 @@ Themes that ship their own side cart JavaScript need to render properties there
-### Behavior to Expect
+## Behavior to Expect
| Behavior | Detail |
| ----- | ------ |
@@ -83,7 +83,7 @@ Themes that ship their own side cart JavaScript need to render properties there
| File uploads | File inputs are not supported. Inputs with `type="file"` are ignored. |
| Set once | Properties are captured when the line is added to the cart. There is no update path for changing them afterwards. |
-### Add Properties with the Storefront GraphQL API
+## Add Properties with the Storefront GraphQL API
Themes that add to the cart through the [Storefront GraphQL API](/docs/storefront/graphql) pass properties on each line as a JSON object of name and value pairs. The field is available on [createCart](/docs/storefront/graphql/mutations/create-cart) and [addCartLines](/docs/storefront/graphql/mutations/add-cart-lines), and is returned on cart lines as `properties { key value }`.
@@ -106,7 +106,7 @@ Themes that add to the cart through the [Storefront GraphQL API](/docs/storefron
`properties` must be a JSON object. Any other value returns the error `Properties must be a JSON object.`
-### Related
+## Related
Using the choice fields from the template is entirely optional. Theme developers can create their own custom choice selectors using the `product.data` json object for a more customized user experience.
-### Map Choices to Variants
+## Map Choices to Variants
With the variant choices now available in the template, it is now necessary to map choices from the `variant_form` choices to variant product IDs.
diff --git a/content/docs/storefront/themes/index.mdx b/content/docs/storefront/themes/index.mdx
index c45f314..f6f8f89 100644
--- a/content/docs/storefront/themes/index.mdx
+++ b/content/docs/storefront/themes/index.mdx
@@ -15,7 +15,7 @@ import IntroTheme from '../../../_snippets/_view-intro-theme.mdx';
-### Layout & Structure
+## Layout & Structure
The Storefront theme framework has a set guideline for the base directories of your theme for your assets, html, and settings.
```shell title="Storefront Theme Structure"
@@ -31,7 +31,7 @@ theme
```
-### Assets
+## Assets
The assets directory is used to upload static asset files used in the theme such as images, stylesheets, web fonts, and javascript files. The assets directory works in conjunction with the [`asset_url` template filter](/docs/storefront/themes/templates/filters#asset_url) to render the full path on your storefront.
```django title="Example link in template to /assets/css/style.css"
@@ -42,7 +42,7 @@ The assets directory is used to upload static asset files used in the theme such
Never hardcode a CDN asset URL in a template — asset URLs change on every push and the hardcoded link will break. Use `asset_url` for all theme asset references.
-### Configs
+## Configs
The configs directory is used to store your theme settings options and also the settings data as they should be configured with the theme.
- `settings_schema.json` is used to generate the theme settings form
@@ -55,7 +55,7 @@ configs
```
[See Theme Settings Guide](/docs/storefront/themes/settings)
-### Locales
+## Locales
The `locales` directory is used to for storefront theme translation json files. The translation files are used in conjunction with the translation template tag to support multiple languages for your storefront.
@@ -71,7 +71,7 @@ locales
```
[See Translations Guide](/docs/storefront/themes/translations)
-### Layouts
+## Layouts
The `layouts` directory is used to store base templates that are then extended from in view specific templates, see extends and block template tags for more on template inheritance. See the [`extends` template tag](/docs/storefront/themes/templates/tags#extends--block) for more on template inheritance.
```shell title="Layouts Directory Example"
@@ -79,7 +79,7 @@ layouts
└── base.html
```
-### Partials
+## Partials
The partials directory is used to store reusable which are reusable snippets of code that can be used in tandem with the include template tag for reuse across many templates. See the includes template tag for more on template inheritance with partials.
```shell title="Partials Directory Example"
@@ -98,7 +98,7 @@ partials
```
-### Templates
+## Templates
The templates directory is used to store all templates for a theme, see [URLs and Template Paths](/docs/storefront/themes/templates/urls-and-template-paths) for reference.
```shell title="Templates Directory Example"
@@ -128,14 +128,14 @@ templates
└── index.html
```
-### Sass
+## Sass
The sass directory accepts scss files for use in a theme. See Theme Kit for more details on local sass compiling.
Sass files are not automatically compiled in the platform and must be compiled to css files locally for use in templates from the assets directory.
-### Theme Kit
+## Theme Kit
[Theme Kit](https://github.com/NextCommerceCo/theme-kit) is a command line tool for developers to build an maintain storefront themes programmatically, allowing theme developers to:
diff --git a/content/docs/storefront/themes/settings.mdx b/content/docs/storefront/themes/settings.mdx
index c193fa5..b8312b0 100644
--- a/content/docs/storefront/themes/settings.mdx
+++ b/content/docs/storefront/themes/settings.mdx
@@ -9,13 +9,13 @@ sidebar_position: 3
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
-### Introduction
+## Introduction
Theme settings are the power behind the dashboard theme editor experience allowing users to customize the look and feel of their storefront without needing to know how to code.
{/* Image: theme-customize-editor.jpg */}
-### Theme Settings Location
+## Theme Settings Location
Theme settings consist of two JSON files in the `/configs` directory.
@@ -28,7 +28,7 @@ configs
- `settings_schema.json` - Used to create the settings schema to create settings shown in the dashboard theme editor.
- `settings_data.json` - Used to store theme settings values for access in templates for rendering.
-### Using Settings in Templates
+## Using Settings in Templates
Settings are passed to templates settings context variable allowing you to access settings values by their name. See example below of changing the layout by conditionally adding a class based on a radio setting.
@@ -85,7 +85,7 @@ Settings are passed to templates settings context variable allowing you to acces
-### Attribute Reference
+## Attribute Reference
| Attribute | Required | Description |
| -----------| --------------------|---------------- |
diff --git a/content/docs/storefront/themes/templates/index.mdx b/content/docs/storefront/themes/templates/index.mdx
index 83918f8..56c0d86 100644
--- a/content/docs/storefront/themes/templates/index.mdx
+++ b/content/docs/storefront/themes/templates/index.mdx
@@ -6,14 +6,14 @@ sidebar_position: 1
import { Callout } from 'fumadocs-ui/components/callout';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
-### Introduction
+## Introduction
The storefront theme templates language is designed to be both powerful and easy to use. If you have any exposure to working with other text-based template languages such as Jinja2 or Liquid, you should feel right at home.
The storefront theme template system provides **tags, filters** and **variables** for control flow logic inside of a template.
-### Variables
+## Variables
Variables look like this: `{{ variable }}` and contain the content the template uses to render to the page. Variables contain a dictionary structure of content and use . notation to access attributes.
@@ -34,7 +34,7 @@ Variables look like this: `{{ variable }}` and contain the content the template
-### Filters
+## Filters
Filters allow you to modify the output of a variables and look like this `{{ customer.name|title }}`. This would display the value of `{{ customer.name }}` after being filtered there the title filter to make format the string to title case. See built-in filter reference.
@@ -57,7 +57,7 @@ Filters allow you to modify the output of a variables and look like this `{{ cus
-### Tags
+## Tags
Tags can do many things such as control flow, iterations, template inheritance, and theme translations. Tags look like this `{% tag %}` . [See built-in tag reference](/docs/storefront/themes/templates/tags).
diff --git a/content/docs/storefront/themes/templates/objects.mdx b/content/docs/storefront/themes/templates/objects.mdx
index 2aae248..be5fcaa 100644
--- a/content/docs/storefront/themes/templates/objects.mdx
+++ b/content/docs/storefront/themes/templates/objects.mdx
@@ -637,7 +637,7 @@ The session object is returned by the [`purchase_info_for_product`](/docs/storef
{% endif %}
```
-**session.price**
+#### session.price
| Property | Type | Description |
| ----- | ------ | ------ |
@@ -647,7 +647,7 @@ The session object is returned by the [`purchase_info_for_product`](/docs/storef
| `currency` | String | The currency code for this price. |
| `excl_tax` | Decimal | The price excluding tax. |
-**session.availability**
+#### session.availability
| Property | Type | Description |
| ----- | ------ | ------ |
@@ -777,7 +777,7 @@ Cart line object available on the cart page (`templates/cart.html`) through the
| ----- | ------ | ------ |
| `properties` | List | Line item properties captured on the product page, see [Personalized Products](/docs/storefront/themes/guides/personalized-products). Property names starting with an underscore are excluded. |
-**line.properties**
+#### line.properties
| Property | Type | Description |
| ----- | ------ | ------ |
diff --git a/content/docs/storefront/themes/templates/tags.mdx b/content/docs/storefront/themes/templates/tags.mdx
index 7354c35..6e0b890 100644
--- a/content/docs/storefront/themes/templates/tags.mdx
+++ b/content/docs/storefront/themes/templates/tags.mdx
@@ -9,7 +9,7 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
Template tags enable theme developers to include and extend templates and blocks, add logical operators, query and filter data, and much more. See all available template tags below.
-### app_asset_url
+## app_asset_url
The `app_asset_url` tag is used to reference asset files included in app snippets.
@@ -17,7 +17,7 @@ The `app_asset_url` tag is used to reference asset files included in app snippet
```
-### app_hook
+## app_hook
The `app_hook` tag specifies a theme storefront location Apps can inject snippets into to extend storefront templates from Apps. Theme developers should ensure their templates include all available `app_hooks` to ensure compatibility with all Apps.
@@ -33,7 +33,7 @@ import AppHookLocations from '../../../../_snippets/_app-hook-locations.mdx';
-### add_query_param
+## add_query_param
The `add_query_param` tag appends or updates a query parameter on the current URL. Commonly used for building pagination links and filter URLs while preserving existing query parameters.
@@ -65,7 +65,7 @@ The `add_query_param` tag appends or updates a query parameter on the current UR
| param_name | The query parameter name to set, eg `'page'`. |
| value | The value to assign to the parameter. |
-### annotate_form_field
+## annotate_form_field
The `annotate_form_field` tag adds HTML attributes to a form field based on its Django form field properties (required, type, etc.). Useful for adding client-side validation and accessibility attributes.
@@ -74,7 +74,7 @@ The `annotate_form_field` tag adds HTML attributes to a form field based on its
{{ field }}
```
-### boolean operators
+## boolean operators
If tags may be used in combination with boolean operators for conditional control flow.
| Operator | Description |
@@ -93,7 +93,7 @@ If tags may be used in combination with boolean operators for conditional contro
| `<=` | less than or equal to |
| `>=` | greater than or equal to |
-### cart_form
+## cart_form
The `cart_form` tag generates an add-to-cart form for a product. Required on every product page to enable purchasing.
@@ -156,7 +156,7 @@ The tag returns a form object, not rendered HTML. Loop over it to render each fi
Add [line item property](/docs/storefront/themes/guides/personalized-products) inputs to this form to capture customer personalization such as an engraving or gift message.
-### comment
+## comment
Ignores everything between `{% comment %}` and `{% endcomment %}`. An optional note may be inserted in the first tag. For example, this is useful when commenting out code for documenting why the code was disabled.
@@ -167,7 +167,7 @@ Ignores everything between `{% comment %}` and `{% endcomment %}`. An optional n
{% endcomment %}
```
-### core_js
+## core_js
The `core_js` tag outputs the platform's core JavaScript bundle. This is required in every theme's base layout and powers cart functionality, AJAX form submissions, CSRF token handling, and other platform features.
@@ -188,7 +188,7 @@ The `core_js` tag outputs the platform's core JavaScript bundle. This is require
jQuery must be loaded before `{% core_js %}`. The platform's core JavaScript depends on jQuery being available in the global scope.
-### csrf_token
+## csrf_token
This tag is used for CSRF protection and required on any template with a form that sends a POST request to the back end.
@@ -200,7 +200,7 @@ This tag is used for CSRF protection and required on any template with a form th
```
-### extends & block
+## extends & block
Extends and block tags allow you to define blocks of content in a base template that can be overridden by templates that extend from it for template inheritance.
@@ -250,7 +250,7 @@ Extends and block tags allow you to define blocks of content in a base template
-### for
+## for
Loops over each item in array, making the item available in a context variable. For example, to display a list of products provided in the `{{ products }}` variable.
@@ -262,7 +262,7 @@ Loops over each item in array, making the item available in a context variable.
```
-### if, elif, & else
+## if, elif, & else
Use the if tag to evaluate if a variable is "true" and control the contents displayed.
```django title="if, elif, & else"
@@ -275,7 +275,7 @@ Use the if tag to evaluate if a variable is "true" and control the contents disp
{% endif %}
```
-### include
+## include
Loads a template and renders it with the current context. This is a way of including other templates within a template.
@@ -290,7 +290,7 @@ Loads a template and renders it with the current context. This is a way of inclu
A word of caution, multi-level inclusion inside of iterative loops can create performance penalties while rendering a page html for site visitors. Use **includes** sparingly when working inside iterative loops.
-### image_thumbnail
+## image_thumbnail
The `image_thumbnail` tag is used to resize images dynamically in templates. The tag accepts arguments that control how the image is resized.
```django title="image_thumbnail"
@@ -314,13 +314,13 @@ The `image_thumbnail` tag is used to resize images dynamically in templates. The
|padding|Padding is a boolean and controls if the image should be padded to fit the specified geometry.|
-### now
+## now
Displays the current date and/or time, using a format according to the given string. [See available date reference for format options](https://docs.djangoproject.com/en/dev/ref/templates/builtins/#date).
-### purchase_info_for_product
+## purchase_info_for_product
The `purchase_info_for_product` tag is used to retrieve the price of a product in the current user session's currency.
@@ -337,7 +337,7 @@ The `purchase_info_for_product` tag is used to retrieve the price of a product i
| product | Must pass the current `product` context object. |
-### purchase_info_for_line
+## purchase_info_for_line
The `purchase_info_for_line` tag retrieves the price and availability of a cart line item in the current session's currency. Works the same as `purchase_info_for_product` but accepts a cart line object.
@@ -353,7 +353,7 @@ The `purchase_info_for_line` tag retrieves the price and availability of a cart
| request | Must pass the current `request` context object. |
| line | Must pass a cart `line` context object. |
-### render_field
+## render_field
The `render_field` tag renders a form field with additional HTML attributes. Use it to add CSS classes, placeholders, and other attributes to Django form fields in templates.
@@ -379,7 +379,7 @@ The `render_field` tag renders a form field with additional HTML attributes. Use
| field | The form field object to render. |
| attributes | HTML attributes to add, using `attr="value"` or `attr+="value"` (append) syntax. |
-### seo
+## seo
The `seo` tag generates SEO meta data for products in standardized format for consumption by 3rd party systems.
```django title="seo"
@@ -388,7 +388,7 @@ The `seo` tag generates SEO meta data for products in standardized format for co
The tag is expected to be added to the top of product details template to generate necessary SEO meta data.
-### t
+## t
The `t` (translation) tag is used to display localized content from a theme's translations files. The t tag accepts a key and additional replacement variable arguments to access the theme translations and return the language appropriate string for display to the user.
@@ -396,7 +396,7 @@ The `t` (translation) tag is used to display localized content from a theme's tr
{% t 'customer.orders.order_count' with count=orders.count %}
```
-### url
+## url
Returns an absolute url path reference matching a given view with parameters. See the URL & Template Path reference for a list of all URL names to use with the `{% url %}` template tag.
@@ -404,7 +404,7 @@ Returns an absolute url path reference matching a given view with parameters. Se
Blog
```
-### where
+## where
Queries and filters store objects to dynamically assign objects to a variable.
diff --git a/content/docs/storefront/themes/templates/urls-and-template-paths.mdx b/content/docs/storefront/themes/templates/urls-and-template-paths.mdx
index aade9a1..aa8ab0a 100644
--- a/content/docs/storefront/themes/templates/urls-and-template-paths.mdx
+++ b/content/docs/storefront/themes/templates/urls-and-template-paths.mdx
@@ -17,20 +17,20 @@ import IntroTheme from '../../../../_snippets/_view-intro-theme.mdx';
Ensure your template paths match with expected template paths for built-in storefront views. Use the public themes on [GitHub](https://github.com/NextCommerceCo/) as a reference guide and starting point. All URL paths are automatically localized to the users language following your store's Localization settings.
-### Homepage
+## Homepage
| URL Name | URL Path | Template Path |
| --- | --- | --- |
| N/A | / | templates/index.html |
-### Blog
+## Blog
| URL Name | URL Path & Arguments | Template Path |
| --- | --- | --- |
| blog:blog-list | /blog/ | templates/blog/index.html |
| blog:blog-detail | /blog/detail/:post_slug/ | templates/blog/post.html |
-### Cart
+## Cart
| URL Name | URL Path | Template Path |
| --- | --- | --- |
@@ -40,7 +40,7 @@ Ensure your template paths match with expected template paths for built-in store
| cart:vouchers-add | POST /cart/vouchers/add/ | N/A (action endpoint) |
| cart:vouchers-remove | POST /cart/vouchers/remove/:voucher_id/ | N/A (action endpoint) |
-### Catalogue
+## Catalogue
| URL Name | URL Path & Arguments | Template Path |
| --- | --- | --- |
@@ -50,33 +50,33 @@ Ensure your template paths match with expected template paths for built-in store
-### Checkout
+## Checkout
| URL Name | URL Path & Arguments | Template Path |
| --- | --- | --- |
| checkout:shipping-address | checkout/* | checkout/checkout.html |
-### Pages
+## Pages
| URL Name | URL Path & Arguments | Template Path |
| --- | --- | --- |
| N/A | /:page_slug | templates/pages/page.html |
-### Reviews
+## Reviews
| URL Name | URL Path & Arguments | Template Path |
| --- | --- | --- |
| catalogue:reviews-list | /catalogue/:product_slug/reviews/ | templates/reviews/index.html |
| catalogue:reviews-detail | /catalogue/:product_slug/reviews/:id/ | templates/reviews/review.html |
| catalogue:reviews-add | /catalogue/:product_slug/reviews/add/ | templates/reviews/form.html |
-### Search
+## Search
| URL Name | URL Path | Template Path |
| --- | --- | --- |
| search:search | /search/ | templates/search.html |
-### Support
+## Support
| URL Name | URL Path | Template Path |
| --- | --- | --- |
@@ -84,7 +84,7 @@ Ensure your template paths match with expected template paths for built-in store
| support:article-list | /support/categories/:category_slug/ | templates/support/category.html |
| support:article-detail | /support/articles/:article_slug/ | templates/support/article.html |
-### Customer / Authentication
+## Customer / Authentication
| URL Name | URL Path | Template Path |
| --- | --- | --- |
@@ -93,7 +93,7 @@ Ensure your template paths match with expected template paths for built-in store
| customer:summary | /accounts/ | N/A (platform-managed) |
| customer:support-ticket-create | /accounts/support/create/ | N/A (platform-managed) |
-### Localization
+## Localization
These are POST action endpoints used in forms for switching language, currency, or storefront geo.
@@ -103,13 +103,13 @@ These are POST action endpoints used in forms for switching language, currency,
| core:set-currency | POST | Change the active currency. |
| core:set-storefront | POST | Change the active storefront geo (country, language, currency). |
-### API
+## API
| URL Name | URL Path | Description |
| --- | --- | --- |
| storefrontapi:graphql | /api/graphql/ | [Storefront GraphQL API](/docs/storefront/graphql) endpoint. |
-### Error Pages
+## Error Pages
| URL Name | URL Path | Template Path |
| --- | --- | --- |
diff --git a/content/docs/storefront/themes/theme-kit.mdx b/content/docs/storefront/themes/theme-kit.mdx
index 553b5f1..137af6e 100644
--- a/content/docs/storefront/themes/theme-kit.mdx
+++ b/content/docs/storefront/themes/theme-kit.mdx
@@ -18,7 +18,7 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
[See Full Instructions on GitHub](https://github.com/NextCommerceCo/theme-kit) or [Install Theme Kit from PyPI](https://pypi.org/project/next-theme-kit/)
-### Installation
+## Installation
Theme Kit is a python package available on [PyPI](https://pypi.org/project/next-theme-kit/)
@@ -28,10 +28,10 @@ If you already have `python` and `pip`, install with the following command:
pip install next-theme-kit
```
-#### Mac OSX Requirements
+### Mac OSX Requirements
See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homebrew-and-Python#python-3x). Once you have completed this step you can install using the `pip` instructions above.
-#### Windows Requirements
+### Windows Requirements
* **Option 1 (Recommended)** - Windows 10 and above feature WSL (Windows Subsystem for Linux) which provides a native Linux environment, see how to [Install WSL with Ubuntu](https://docs.microsoft.com/en-us/windows/wsl/install). Once you have installed WSL, follow the [best practice guides to configure and use with VS Code](https://docs.microsoft.com/en-us/windows/wsl/setup/environment) and then follow the `pip` instructions above to install Theme Kit.
@@ -40,10 +40,10 @@ See how to install `python` and `pip` with [HomeBrew](https://docs.brew.sh/Homeb
**Use Python Virtual Environments** - For Mac, Windows, and Linux, it's a best practice to use a Python Virtual Environment to isolate python packages and dependencies to reduce potential conflicts or errors, [more on creating a Python Virtual Environment](https://www.freecodecamp.org/news/how-to-setup-virtual-environments-in-python/).
-### Setup
+## Setup
Connect `ntk` to a store in three steps.
-#### 1. Create the API Key
+### 1. Create the API Key
Store authentication uses [OAuth 2.0](https://auth0.com/intro-to-iam/what-is-oauth-2/) and requires creating a store OAuth App with the `themes:read` and `themes:write` permissions.
1. In the Storefront admin, go to **Settings > API Access**.
@@ -52,7 +52,7 @@ Store authentication uses [OAuth 2.0](https://auth0.com/intro-to-iam/what-is-oau
4. In the **Permissions** tab, enable `themes:read` and `themes:write`.
5. **Save**. Copy the generated API key — you will need it in the next step.
-#### 2. Configure Theme Kit
+### 2. Configure Theme Kit
`ntk` reads its connection settings from two places: command flags (`--apikey`, `--store`, `--theme_id`) and the `config.yml` file in your theme directory. You do not need to create `config.yml` by hand — `ntk checkout` and `ntk init` write it for you, and after that commands run without flags:
```yaml title="config.yml (written by ntk checkout / ntk init)"
@@ -70,7 +70,7 @@ Keep the API key out of source control. Do not commit `config.yml` to git if it
`config.yml` supports multiple environments. Commands use the `development` entry by default; pass `-e` / `--env` to target another environment (e.g. `ntk push --env=production`). The `[development]` prefix in command output is the active environment.
-#### 3. Connect to a Theme
+### 3. Connect to a Theme
Work from a copy of an existing theme rather than an empty directory — a complete theme is the reference for the required directories, templates, and settings.
**Work on a theme already on the store** — `ntk checkout` downloads the theme into your current directory and writes `config.yml`:
@@ -86,7 +86,7 @@ ntk init --name="" --apikey="" --store="https://{store}.29n
ntk push
```
-### Usage
+## Usage
With the package installed, you can now use the commands inside your theme directory and work on a storefront theme.
| Command | Description |
| ----------- | ------------------------------------ |
@@ -99,7 +99,7 @@ With the package installed, you can now use the commands inside your theme direc
| `ntk sass` | Process sass to css, see [Sass Processing](#sass-processing) |
-#### Browse Store Themes
+### Browse Store Themes
To see what themes exist on the store, run `ntk list` to print the theme ID and name of each, with the active theme marked.
```bash
@@ -116,7 +116,7 @@ Output looks like:
If you do not have a `config.yml`, also pass `--apikey` and `--store`.
-#### Work on an Existing Theme
+### Work on an Existing Theme
To start working on a theme that already exists on the store, `ntk checkout` downloads it into your directory and writes `config.yml` with the theme ID.
```bash
@@ -131,7 +131,7 @@ ntk checkout --theme_id= --apikey="" --store="https://{store}.29nex
`ntk checkout` differs from `ntk pull` in one way: `checkout` writes `config.yml` so the directory is ready for subsequent `ntk push` / `ntk watch` runs; `pull` downloads the same files without writing `config.yml`.
-#### Add a New Theme to the Store
+### Add a New Theme to the Store
`ntk init` registers your current directory as a new theme on the store and writes a `config.yml`. It does not download or scaffold any files — run it inside an existing theme codebase, then `ntk push` to upload the files.
@@ -150,7 +150,7 @@ ntk init --name="" --apikey="" --store="https://{store}.29n
On success, `ntk init` logs the new theme ID and name, and persists the theme ID into `config.yml` so subsequent commands can omit `--theme_id`.
-#### Sync Files to the Store
+### Sync Files to the Store
To sync files between your local directory and the store, use `ntk push` to upload and `ntk pull` to download. Both upload or download the whole theme by default, and both accept file paths as positional arguments to limit the operation to specific files.
@@ -188,7 +188,7 @@ ntk pull templates/index.html assets/main.css
-#### Watch for File Changes
+### Watch for File Changes
`ntk watch` monitors your theme directory and automatically pushes changed files to the store. Use it while you develop — save a file and the change is uploaded moments later.
```bash
@@ -209,7 +209,7 @@ Deletes sync too — deleting a local file while `ntk watch` is running deletes
`ntk watch` watches the current directory tree (subdirectories included) and only uploads files with valid theme extensions. It does not accept file arguments. To scope changes to specific files, run `ntk push` with file paths instead.
-#### Sass Processing
+### Sass Processing
Theme kit includes support for Sass processing via [Python Libsass](https://sass.github.io/libsass-python/). Sass processing includes support for variables, imports, nesting, mixins, inheritance, custom functions, and more.
diff --git a/content/docs/storefront/themes/translations.mdx b/content/docs/storefront/themes/translations.mdx
index 47674f8..1dfedfa 100644
--- a/content/docs/storefront/themes/translations.mdx
+++ b/content/docs/storefront/themes/translations.mdx
@@ -7,7 +7,7 @@ description: Localize theme templates with the t tag, locale JSON files, variabl
Theme templates can be fully localized with translations so that your store visitors are shown content in their local language. Use the t (translation) tag in your templates to access string translations in the locale files. Learn more about the [t tag](/docs/storefront/themes/templates/tags#t) and theme Locale files.
-### Using Translations in Practice
+## Using Translations in Practice
The `t` tag accepts an initial argument that is the key reference to the translation string in a locale file.
@@ -42,7 +42,7 @@ import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
-### Passing Variable Arguments to Translations
+## Passing Variable Arguments to Translations
You can pass multiple named arguments to translations through the `t` tag used in the translation.
@@ -75,7 +75,7 @@ You can pass multiple named arguments to translations through the `t` tag used i
-### Pluralization Support
+## Pluralization Support
The t tag accepts two arguments for pluralization:
- Pass the count argument with a value for cardinal pluralization, ie 1, 2, 3, 4.
@@ -90,7 +90,7 @@ Pluralization rules follow [Unicode CLDR](https://github.com/unicode-org/cldr) s
- `few`
- `many`
-#### Cardinal Pluralization
+### Cardinal Pluralization
Cardinal pluralization can be used to display different translations based on the value passed to `count`.
@@ -134,7 +134,7 @@ Cardinal pluralization can be used to display different translations based on th
-#### Ordinal Pluralization
+### Ordinal Pluralization
Ordinal pluralization can be used to display different translations based on the index value to display the ordering of an object.
diff --git a/content/docs/webhooks/index.mdx b/content/docs/webhooks/index.mdx
index 29e0bcf..20fcbb5 100644
--- a/content/docs/webhooks/index.mdx
+++ b/content/docs/webhooks/index.mdx
@@ -8,7 +8,7 @@ Use webhooks to be notified about events that happen in your store.
Stores can send webhooks that notify your application anytime an event happens. This is especially useful for building custom reporting solutions that need to receive data on order or customer activity.
-### Why Webhooks
+## Why Webhooks
Webhooks are an efficient way to sync data from a store in near real time, keeping your app up to date without the overhead of traditional polling. See the example below for subscribing to `order.created` events.
@@ -20,7 +20,7 @@ sequenceDiagram
Store->>App: Sends order.created event payload
```
-### Use Cases
+## Use Cases
Common use cases include, but are not limited to:
@@ -30,7 +30,7 @@ Common use cases include, but are not limited to:
- Integrating with dispute management services
-### Setting Up Webhooks
+## Setting Up Webhooks
You can register new webhooks through **Settings > Webhooks** or the Admin API to send event data to your application endpoint. For each webhook, you can subscribe to all events or select specific events to send to your endpoint. See a list of all events and example event data below.
@@ -44,7 +44,7 @@ Webhook handlers should also complete within about 20 seconds. Longer-running en
Returning a `410` response code indicates the target resource is no longer available and will automatically disable the webhook.
-### Delivery Guarantees
+## Delivery Guarantees
Webhooks are delivered at least once. Every event is queued and retried until your endpoint returns a `200`. The `event_id` stays the same across retries of the same event, so you can use it to skip events you've already processed.
@@ -56,7 +56,7 @@ Because events can arrive out of order, use the timestamps in the payload data t
We also recommend processing events asynchronously so that spikes in delivery volume don't overwhelm your endpoint.
-### Webhook Events
+## Webhook Events
| Event | Description | Reference |
| ----------- | ------------------------------------ | ----- |
@@ -95,7 +95,7 @@ There is no renewal-specific event. A renewal charge arrives as `transaction.cre
Chargebacks and pre-chargeback alerts both arrive as `dispute.created` and `dispute.updated`; the dispute's `type` field says which it is. See the [Disputes guide](https://docs.nextcommerce.com/docs/features/payments/disputes-guide).
-### Webhook Data Structure
+## Webhook Data Structure
Webhook payloads follow the same structure as Admin API data serializers, which makes them predictable. In general, the data in a webhook payload matches the data you would get by retrieving the same resource through the API. You can set up test webhooks and view the webhook logs in the dashboard to help build and verify your receiver.
@@ -148,16 +148,16 @@ Below is a full example of a webhook payload for a `customer.created` event to d
}
```
-### Webhook API Versions
+## Webhook API Versions
Webhook object data structure follows the [Admin API](/docs/admin-api) and Admin API versioning to ensure predictable data structure for existing webhook receiver endpoints with a path for upgrades.
-**Handling Webhook API Versions**
+### Handling Webhook API Versions
Your app can add handling logic using the `api_version` key when receiving and processing data to handle multiple webhook data structures while upgrading to a newer webhook api version.
-### Verifying Webhook Requests
+## Verifying Webhook Requests
Webhook endpoints are generally open to the internet and therefore it's a best practice to verify the payload data.
diff --git a/package.json b/package.json
index 2a0aec2..af75814 100644
--- a/package.json
+++ b/package.json
@@ -16,7 +16,8 @@
"validate-links": "npm run generate && node scripts/validate-links.mjs",
"check-agent-surfaces": "node scripts/check-agent-surfaces.mjs",
"check-frontmatter": "node scripts/check-frontmatter.mjs",
- "check": "npm run check-agent-surfaces && npm run check-frontmatter && node scripts/validate-links.mjs",
+ "check": "npm run check-agent-surfaces && npm run check-frontmatter && npm run check-markup && node scripts/validate-links.mjs",
+ "check-markup": "node scripts/check-markup.mjs",
"check-live-surfaces": "node scripts/check-live-surfaces.mjs",
"postinstall": "patch-package"
},
diff --git a/scripts/check-markup.mjs b/scripts/check-markup.mjs
new file mode 100644
index 0000000..f345501
--- /dev/null
+++ b/scripts/check-markup.mjs
@@ -0,0 +1,77 @@
+/**
+ * Markup rules that keep pages rendering the same way across the docs sites.
+ *
+ * 1. headings are plain text: no **bold** inside a heading
+ * 2. the page title is the only h1, so body headings start at h2 and
+ * never skip a level (h2 then h4)
+ * 3. no empty headings, and the first heading doesn't repeat the page title
+ * 4. a Callout heading goes in its title prop, not a bold first line
+ * (checked when the opening tag sits on its own line)
+ * 5. bold markers inside link text are balanced
+ *
+ * Imported snippets are checked from h3, because they render under an h2.
+ * Only git-tracked pages are read: the generated reference trees are ignored,
+ * and the committed GraphQL reference is regenerated from the schema.
+ */
+
+import { execFileSync } from 'node:child_process';
+import { readFileSync } from 'node:fs';
+import { join, dirname } from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..');
+const files = execFileSync('git', ['ls-files', 'content/docs', 'content/_snippets'], { cwd: ROOT, encoding: 'utf8' })
+ .split('\n')
+ .filter((f) => /\.mdx?$/.test(f) && !f.startsWith('content/docs/storefront/graphql/'));
+
+const errors = [];
+const norm = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, '');
+
+for (const rel of files) {
+ const lines = readFileSync(join(ROOT, rel), 'utf8').split('\n');
+ const snippet = rel.includes('_snippets');
+ let i = 0;
+ let title = '';
+ if (lines[0] === '---') {
+ i = lines.indexOf('---', 1) + 1;
+ const m = lines.slice(1, i).map((l) => /^title:\s*["']?(.*?)["']?\s*$/.exec(l)).find(Boolean);
+ if (m) title = m[1];
+ }
+ let inCode = false;
+ let prev = snippet ? 2 : 1;
+ let first = true;
+ for (; i < lines.length; i++) {
+ const line = lines[i];
+ if (/^\s*(```|~~~)/.test(line)) inCode = !inCode;
+ if (inCode) continue;
+ const at = `${rel}:${i + 1}`;
+ const heading = /^(#{1,6})(?:\s+(.*))?$/.exec(line);
+ if (heading) {
+ const level = heading[1].length;
+ const text = (heading[2] ?? '').trim();
+ if (!text) errors.push(`${at} empty heading`);
+ if (first && title && norm(text) === norm(title)) errors.push(`${at} heading repeats the page title: ${text}`);
+ if (text.includes('**')) errors.push(`${at} bold inside a heading: ${line.trim()}`);
+ if (level > prev + 1) errors.push(`${at} h${level} follows h${prev}; use h${prev + 1}`);
+ if (level === 1) errors.push(`${at} h1 in the body; the frontmatter title is the page h1`);
+ prev = level;
+ first = false;
+ continue;
+ }
+ for (const link of line.matchAll(/\[([^\]\n]*)\]\(/g)) {
+ if ((link[1].match(/\*\*/g) ?? []).length % 2) errors.push(`${at} unbalanced ** in link text: [${link[1]}]`);
+ }
+ if (/^]*\btitle=)[^>]*>\s*$/.test(line)) {
+ const next = lines.slice(i + 1).find((l) => l.trim() !== '');
+ if (next && /^\s*\*\*[^*]+\*\*\s*$/.test(next)) {
+ errors.push(`${at} Callout opens with a bold line; pass it as title="${next.trim().replace(/\*\*/g, '')}"`);
+ }
+ }
+ }
+}
+
+if (errors.length) {
+ console.error(`check-markup: ${errors.length} problem(s)\n ${errors.join('\n ')}`);
+ process.exit(1);
+}
+console.log('check-markup: ok');