Profile Pages
Profile pages are customer account pages in the webshop. Templates control their structure and visual design, while the built-in Vue behavior loads customer data and handles interactions.
The recommended split is:
- Twig controls page structure, navigation, loading states, and styling.
- Built-in Vue modules control customer data, forms, and interactive behavior.
- Templates use Vue bindings to display the data supplied by those modules.
You do not need to create API requests or authentication logic for these pages.
Profile Page Files
Profile pages are grouped in the pages/profile folder:
pages/
profile/
orders.twig
my-profile.twig
addresses.twig
help.twig
login.twig
register.twig
| Page | URL | File | Mount point |
|---|---|---|---|
| Orders | /profile | pages/profile/orders.twig | #orders |
| Customer information | /profile/my-profile | pages/profile/my-profile.twig | #user_info |
| Saved addresses | /profile/saved-addresses | pages/profile/addresses.twig | #addresses |
| Saved cards | /profile/saved-cards | pages/profile/cards.twig | #cards |
| Help (customer service) | /profile/help | pages/profile/help.twig | #help |
| Notifications | /profile/notifications | pages/profile/notifications.twig | |
| My products | /profile/my-products | pages/profile/products.twig | |
| Wishlist | /profile/wishlist | pages/profile/wishlist.twig | |
| Login | /login | pages/profile/login.twig | #login |
| Registration | /register | pages/profile/register.twig | #register |
Orders, customer information, saved addresses, saved cards, my products and notifications need a logged-in customer: a
visitor is sent to the login. The help page and the wishlist are open to visitors. The URLs above are under the sale
channel's prefix (/{language}/{slug}/profile); build the menu links of these pages with
shop_url, as the short form is only forwarded by the platform.
Two pages are optional: My products and Wishlist exist only when the template has their file; without it the visit is forwarded to the orders page, so the menu should link to them only when the template has them.
The Help page is the customer service page: the customer's name, e-mail and phone, a subject and a message. When the
sale channel's show_tickets setting is on (webshop.sale_channel.show_tickets) it also lists the customer's tickets.
The order management dialog opens from the orders page, and a return that cannot start there continues on the help page
(help_url), see Order management dialog.
The log out page (/profile/log-out) is the engine's own and has no template file.
---|---|---|
| Orders | pages/profile/orders.twig | #orders |
| Saved addresses | pages/profile/addresses.twig | #addresses |
| Login | pages/profile/login.twig | #login |
| Registration | pages/profile/register.twig | #register |
Other account pages may be added to the same folder as they become template-ready.
Orders Page
The orders page must have a root element with the orders ID. The built-in orders module mounts automatically when this element exists:
<div id="orders" v-cloak>
<!-- orders page markup -->
</div>
Use v-cloak to prevent Vue expressions from appearing before the page finishes loading.
The template should provide loading, error, and content states:
<div v-if="orders === null && !ordersError">
<!-- loading or skeleton state -->
</div>
<p v-else-if="ordersError" v-text="ordersError"></p>
<div v-else>
<!-- order list -->
</div>
Order List Markup
Orders are available through orders.data. The order card markup belongs directly in the Twig template and can be designed freely:
<template v-for="order in orders.data" :key="order.id">
<article class="order-card">
<h2 v-text="order.pretty_id"></h2>
<span v-text="order.status_label"></span>
<span v-text="order.product_name"></span>
<a :href="order.url">
View order
</a>
</article>
</template>
You can change the HTML structure, CSS classes, layout, buttons, spacing, and responsive behavior without changing the orders module.
Do not create a separate single-order component for this page. Keeping the order markup in the Twig file allows every template to use its own order-card design.
Order Values
The orders module prepares common display values for the template:
| Value | Description |
|---|---|
order.pretty_id | Customer-facing order number |
order.created_at | Order date |
order.status_label | Localized order status |
order.product_name | Product name when the order contains one product |
order.item_count | Number of ordered items |
order.exchange_item_count | Number of exchanged items |
order.price.amount | Order total |
order.price.currency | Currency code |
order.products | Products included in the order |
product.main_image | Main image for a product |
order.orderItems | Original order item data |
Product images can be rendered like this:
<div v-for="product in order.products" :key="product.id">
<img
v-if="product.main_image"
:src="product.main_image"
alt=""
>
</div>
Prefer the prepared values such as status_label, product_name, and product.main_image instead of repeating data transformation logic in Twig.
Product Counts
When an order has no single product name, display its item count in the template:
<span v-if="order.exchange_item_count > 0">
<span v-text="order.item_count"></span>
{{ 'profile.item'|trans }},
<span v-text="order.exchange_item_count"></span>
{{ 'profile.item_changed'|trans }}
</span>
<span v-else-if="order.product_name" v-text="order.product_name"></span>
<span v-else>
<span v-text="order.item_count"></span>
{{ 'profile.item'|trans }}
</span>
Twig owns the translated labels. Vue supplies only the dynamic numbers and product values.
Saved Addresses
The saved addresses page uses the addresses mount point. Addresses are available through addresses and support the built-in edit and delete actions:
<div id="addresses" v-cloak>
<article v-for="address in addresses" :key="address.id">
<h2><span v-text="address.postalCode"></span> <span v-text="address.city"></span></h2>
<p><span v-text="address.street"></span> <span v-text="address.house"></span></p>
<button @click="loadModalModule('addressModal', address.id)">
Edit
</button>
<button @click="loadDialogModule('deleteDialog', address.id, address.userId)">
Delete
</button>
</article>
<button @click="loadModalModule('addressModal')">
Add address
</button>
</div>
The address editor and delete confirmation are provided by the built-in account behavior.
Login And Registration
Login and registration pages use their own mount points:
<div id="login" v-cloak>
<!-- email and verification-code forms -->
</div>
<div id="register" v-cloak>
<!-- registration form -->
</div>
The login page has two states: email entry and verification-code entry. The registration page supports customer details, phone validation, terms acceptance, and captcha when required. Keep the form fields bound to the documented names used by the built-in behavior.
Account Mount Points
Built-in account modules use mount points. A template only needs to provide the matching element when it wants to display a particular account feature:
| Feature | Mount point |
|---|---|
| Orders | #orders |
| Customer information | #user_info |
| Saved addresses | #addresses |
| Saved cards | #cards |
| Login | #login |
| Registration | #register |
| Help | #help |
The modules only activate on pages where their mount point is present.
Adding A Profile Page
When a new profile page becomes available for templates:
- Add its Twig file under
pages/profile/. - Add the documented mount point.
- Build the complete page structure in Twig.
- Use the documented Vue values and bindings.
- Include loading, empty, error, and logged-out states.
- Add responsive styling for desktop and mobile layouts.
Keep API calls, authentication, validation, and interactive state in the built-in modules. Keep the page markup and visual presentation in the template.