Commera

Commera

Open in ChatGPT
Ask ChatGPT about this page
Open in Claude
Ask Claude about this page

Step 2: Add a layout

In this step, you add the Acme layout. Every Acme page extends it, so the header, the footer and the stylesheets are in one file.

What you'll build

  • components/theme_layout.html, which extends Shop Base Theme's components/base.html
  • A header with the store logo, a Shop link and a cart count
  • A footer with the year and the store name

1. Create the layout file

Create acme_theme/themes/acme/components/theme_layout.html:

{% extends "components/base.html" %}
{% from "components/macros/branding.html" import brand_logo with context %}

{% block head %}
	{# The shared toaster that base.html includes is styled with Tailwind utilities, so a plain-CSS theme still loads them. #}
	<link rel="stylesheet" href="/assets/commera/css/tailwind.css">
	<link rel="stylesheet" href="{{ shop_theme_asset_url('css/acme.css') }}">
{% endblock %}

{% block body_class %}theme-acme{% endblock %}

{% block chrome_top %}
	{% block site_header %}
	<header class="acme-header">
		<a class="acme-brand" href="/{{ frappe.lang or 'en' }}">{{ brand_logo(css_class="acme-logo") }}</a>
		<nav class="acme-nav">
			<a href="/{{ frappe.lang or 'en' }}/products">{{ _("Shop") }}</a>
			<a href="/{{ frappe.lang or 'en' }}/cart">
				{{ _("Cart") }} (<span x-text="$store.cart.items.length">0</span>)
			</a>
		</nav>
	</header>
	{% endblock %}
{% endblock %}

{% block chrome_bottom %}
	{% block site_footer %}
	<footer class="acme-footer">
		<p>&copy; {{ frappe.utils.nowdate()[:4] }} {{ app_name }}</p>
	</footer>
	{% endblock %}
{% endblock %}

components/base.html is not in your theme. Commera finds it in the parent theme, Shop Base Theme. The same is true for components/macros/branding.html, which has the brand_logo() macro.

The cart count reads $store.cart. Shop Base Theme loads that Alpine store on every page, so your layout does not load it.

2. Fill the right blocks

components/base.html has these blocks. Fill the blocks that your theme needs, and leave the others alone.

Block Where it is Fill it with
seo In <head> Leave it. A page sets the seo context variable instead.
json_ld In <head> Leave it. A page sets the json_ld context variable instead.
analytics_head In <head> Leave it. It has the merchant's analytics tags.
alpine_plugins In <head>, before Alpine starts <script> tags for extra Alpine plugins
head End of <head> Your stylesheets, fonts and preload tags
body_class The class of <body> A class for your theme, such as theme-acme
body_attributes Inside the <body> tag Extra attributes. Start with a space: id="bg".
chrome_top Before <main> The header
body Inside <main> The page content. Each page fills this block.
uncontained_body Inside <main>, after body Content that a page adds after its main content
chrome_bottom After <main> The footer
analytics_events End of <body> Leave it. It sends the storefront's analytics events.
script After </body> Your scripts

Name the layout file components/theme_layout.html. Put the header in a block named site_header and the footer in a block named site_footer, as the Acme layout does. The names header and footer also work. The /commera dashboard renders this file to preview the header and the footer, and it empties the block that it does not show. With a different file name or different block names, the preview shows the wrong part of the page.

3. Import macros with context

{% from "components/macros/branding.html" import brand_logo with context %}

4. Load Tailwind for the toast

Shop Base Theme adds a toast, the "Item added to your bag" message, to every page. The toast uses Tailwind CSS classes. Acme is plain CSS, so the layout loads Commera's Tailwind file before its own CSS:

<link rel="stylesheet" href="/assets/commera/css/tailwind.css">
<link rel="stylesheet" href="{{ shop_theme_asset_url('css/acme.css') }}">

Without it, the toast shows as a large unstyled shape under the footer.

Tailwind resets the size and weight of headings. Set h1, h2 and the other headings in your own CSS. Shop Default Theme loads the same file. Load it in a Tailwind theme too, because your own Tailwind build contains only the classes that your templates use.

Next steps

Last updated 5 days ago
Was this helpful?
Thanks!