Skip to main content
Version: 2.0.0

Overriding Cart & Checkout Templates

CSS customizations change how things look. Template overrides change what is actually rendered. Use this approach when you need to:

  • Reorder sections (e.g. move the order summary above the item list)
  • Add new elements (trust badges, upsell panels, custom notices)
  • Remove elements you do not need
  • Change the two-column cart layout to single-column (or vice versa)
  • Replace the checkout layout entirely (e.g. multi-step vs. one-page)

How template overrides work

yStore resolves templates using Craft's standard template override mechanism. If a file exists in your project's templates/ directory at the same path as a plugin template, your file takes precedence. The plugin template is never loaded.

Plugin provides:   vendor/yui/craft-plugin/src/templates/yui/pages/cart/view.twig
Your override: templates/yui/pages/cart/view.twig ← loaded instead

You only need to override the files you actually want to change. Everything else continues using the plugin defaults.

Template tree

The cart and checkout pages are composed of nested layers:

Layout
└── Page template
├── Components
│ └── Blocks
└── Components
└── Blocks

Override at the lowest possible level to minimise maintenance burden. Overriding a whole page template means you own every block inside it — including any future additions by the plugin.

Key files

Cart

FilePurpose
yui/layouts/cart/1column.twigSingle-column layout (full-width items list, totals below)
yui/layouts/cart/2column-right.twigTwo-column layout (items left, summary sidebar right)
yui/pages/cart/view.twigMain cart page — chooses layout, renders components
yui/components/cart/with-items.twigCart with products — items list + footer + coupon
yui/components/cart/no-items.twigEmpty cart state
yui/components/cart/summary.twigTotals, grand total, proceed-to-checkout button

Checkout

FilePurpose
yui/layouts/checkout/1column.twigDefault checkout layout
yui/layouts/checkout/fullpage.twigFull-viewport checkout (used by some payment gateways)
yui/pages/checkout/view.twigMain checkout page
yui/components/checkout/one-page.twigThe entire one-page checkout form
yui/pages/checkout/results.twigOrder confirmation / thank-you page

Example 1 — Custom empty cart message

The empty cart component is a good first override: self-contained, low risk.

Original (yui/components/cart/no-items.twig):

<div class="empty-cart-wrapper">
<div class="empty-cart-message">
<img width="235" height="205" loading="lazy" src="./empty-cart.jpg" alt="Ohhh.."/>
<h2>{{ "Ohhh... Your cart is empty"|t('yui') }}</h2>
<p>{{ "You currently have no items in your shopping cart."|t('yui') }}</p>
<a class="btn btn-primary" href="{{ craft.app.sites.primarySite.baseUrl }}">
{{ "Continue shopping"|t('yui') }}
</a>
</div>
</div>

Your override (templates/yui/components/cart/no-items.twig):

<div class="empty-cart-wrapper">
{{-- Brand hero banner --}}
<div class="empty-cart-banner">
<img src="{{ siteUrl('assets/banners/empty-cart-banner.jpg') }}" alt="" loading="lazy"/>
</div>

<div class="empty-cart-message">
<h2>{{ "Your bag is empty"|t('site') }}</h2>
<p>{{ "Looks like you haven't added anything yet."|t('site') }}</p>

<a class="btn btn-primary" href="{{ siteUrl('shop') }}">
{{ "Start shopping"|t('site') }}
</a>
<a class="btn btn-secondary" href="{{ siteUrl('account/wishlist') }}">
{{ "View your wishlist"|t('site') }}
</a>
</div>
</div>

Example 2 — Change the cart layout to single column

The cart layout is determined by the class on .cart-wrapper. The default two-column layout (column2-right) places the summary sidebar on the right. To force single-column, override the page template:

Your override (templates/yui/pages/cart/view.twig):

{# Copy the original and change the layout include #}
{% extends 'yui/layouts/cart/1column.twig' %}

{% block content %}
<div class="cart-wrapper column1" x-data="cartPage()">
{% if cart.lineItems | length %}
{% include 'yui/components/cart/with-items' %}
{% include 'yui/components/cart/summary' %}
{% else %}
{% include 'yui/components/cart/no-items' %}
{% endif %}
</div>
{% endblock %}

Example 3 — Add a trust bar to the checkout

Override just the checkout layout to inject a persistent element above the form:

Your override (templates/yui/layouts/checkout/1column.twig):

{% extends '_layout' %}

{% block main %}
{{-- Trust signals --}}
<div class="checkout-trust-bar">
<span>🔒 {{ "Secure checkout"|t('site') }}</span>
<span>🚚 {{ "Free shipping on orders over €50"|t('site') }}</span>
<span>↩️ {{ "30-day returns"|t('site') }}</span>
</div>

{{ parent() }}
{% endblock %}

Example 4 — Add an upsell panel inside the cart summary

Override the summary component to append a product suggestion:

Your override (templates/yui/components/cart/summary.twig):

{# Include the default summary behaviour #}
{% include 'yui/components/cart/summary' ignore missing with {
_self: null
} %}

{{-- Upsell: show a related product if cart subtotal is under threshold --}}
{% if cart.itemSubtotal < 50 %}
{% set freeShippingGap = 50 - cart.itemSubtotal %}
<div class="cart-upsell-notice">
<p>{{ "Add {amount} more for free shipping!"|t('site', { amount: freeShippingGap | formatCurrency }) }}</p>
</div>
{% endif %}
Avoid including a template within its own override

If your override file has the same path as the original, do not include itself. Use ignore missing and with { _self: null } as shown above, or restructure so you extend a layout and use blocks.

Keeping overrides maintainable

Template overrides are sticky — when the plugin updates and the original template changes, your override masks the new version. To keep upgrades manageable:

  1. Override at the smallest scope possible. Override a block component rather than the whole page.
  2. Leave a comment at the top of every override file noting why the override exists and what upstream file it shadows.
  3. Check release notes for any changes to templates you have overridden before upgrading.
  4. Prefer CSS when the change is purely visual. Template overrides are for structural changes only.

Checklist before you override

  • Have you found the exact template path by inspecting the plugin source?
  • Is the change structural (HTML) or visual (CSS)? If visual, use CSS variables or an event override instead.
  • Is there a block you can extend rather than replacing the full file?
  • Have you added a comment explaining what the override does?