[ADD] tutorials/website_theme: Add tutorials to build a website theme

closes odoo/documentation#13131

Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Signed-off-by: Céline de Lannoy (cede) <cede@odoo.com>
This commit is contained in:
Brandon Mercier
2025-05-05 16:04:57 +02:00
parent 85915a364c
commit 93931fc28e
29 changed files with 1160 additions and 1 deletions

View File

@@ -82,6 +82,7 @@ source_read_replace_vals = {
'CURRENT_MAJOR_VERSION': current_major_version,
'GITHUB_PATH': f'https://github.com/odoo/odoo/blob/{version}',
'GITHUB_ENT_PATH': f'https://github.com/odoo/enterprise/blob/{version}',
'GITHUB_TUTO_PATH': f'https://github.com/odoo/tutorials/blob/{current_major_branch}',
'OWL_PATH': f'https://github.com/odoo/owl/blob/master',
}

View File

@@ -16,6 +16,7 @@ Tutorials
tutorials/importable_modules
tutorials/mixins
tutorials/pdf_reports
tutorials/website_theme
.. tip::
If you are new to Odoo development, we recommend starting with the :doc:`setup guide
@@ -89,3 +90,9 @@ Expand your knowledge on the server framework
:target: tutorials/pdf_reports
Use QWeb, Odoo's powerful templating engine, to create custom PDF reports for your documents.
.. card:: Build a website theme
:target: tutorials/website_theme
Create a tailored website from scratch fully integrated with Odoo and editable via the Website
Builder.

View File

@@ -13,7 +13,7 @@ Customizing the web client
This guide is about creating modules for Odoo's web client.
To create websites with Odoo, see :doc:`website`; to add business capabilities
To create websites with Odoo, see :doc:`website_theme`; to add business capabilities
or extend existing business systems of Odoo, see :doc:`backend`.
.. warning::

View File

@@ -0,0 +1,54 @@
:show-content:
:show-toc:
:hide-page-toc:
=====================
Build a website theme
=====================
| For this project, we'll collaborate on creating a custom website theme fully integrated with Odoo.
| Our client, Airproof, has provided their latest design for their waterproof drone e-commerce,
which we'll replicate.
To start, you must have :doc:`installed Odoo locally </administration/on_premise/source>`.
You will also need some knowledge in:
- XML
- JavaScript (not mandatory)
- Bootstrap 5.1.3
- SCSS
- QWeb (Odoo's own templating system)
- OWL (JavaScript framework, not mandatory)
| **Goal**
| Replicate the Airproof design.
.. image:: website_theme/airproof-home.png
:alt: Airproof homepage.
:align: center
| In the :file:`README.md` of the `Airproof module <{GITHUB_TUTO_PATH}/website_airproof>`_, you can
find the various Airproof designs that you will replicate throughout the different exercises in
this tutorial.
| You can also find all the code necessary for creating the Airproof website there. You should also
obtain this by the end of the tutorial. It is recommended to try solving the exercices first
without looking at the solution!
| **Don't go too fast!**
| Follow the exercises step by step and you will reach the final design at the end of the tutorial.
Throughout this tutorial, you will find "See also" sections leading to parts of the :doc:`How-to
guide: Website themes <../howtos/website_themes>` documentation. Be sure to read this documentation
thoroughly each time! With it, you will find the solution to every exercise.
Ready? Let's get started!
.. toctree::
:maxdepth: 2
website_theme/01_theming
website_theme/02_build_website
website_theme/03_customisation_part1
website_theme/04_customisation_part2
website_theme/05_dynamic_templates
website_theme/06_going_live

View File

@@ -0,0 +1,207 @@
===================
Chapter 1 - Theming
===================
Now that you have Odoo installed and your server is running locally, it's time to create your own
theme module for your website.
.. _tutorials/website_theme/theming/setup:
Setup
=====
| The first step is to ensure that Odoo is running correctly locally. To do this, use a Shell script
to run the server.
| In this script, define the database name and install only the `website` module.
.. seealso::
See reference documentation on how to :ref:`run Odoo <website_themes/setup/getting_started>`.
.. _tutorials/website_theme/theming/module:
Build your module structure
===========================
Now that we know everything is working properly, let's start building our module.
Based on the following structure, start creating your module that will be used as a theme. This is
where you are going to add your XML pages, SCSS, JS, …
.. seealso::
See reference documentation on how to structure your :ref:`theming/module`.
| Start with the basics : :file:`/data`, :file:`/img`, :file:`/scss`, :file:`/js`.
| Don't forget to add the :file:`__init__.py` and :file:`__manifest__.py` files.
In your :file:`__manifest__.py` file, you can declare your module with the following information:
- name (required)
- description
- category
- version
- author
- license
- depends
.. _tutorials/website_theme/theming/odoo_variables:
Declare Odoo variables
======================
In the :file:`primary_variables.scss` file, you can override the default Odoo SCSS variables to
match your design.
Based on the Airproof design, create your :file:`primary_variables.scss` file and define the
following elements:
- Headings font family : Space Grotesk
- Content font family : Lato
- The color palette name and the 5 main colors that compose it: `#000000`, `#BBE1FA`, `#CEF8A1`,
`#FFFFFF`, `#0B8EE6`
- Header & Footer : Use one of the default templates for the moment, we will create a custom header
later.
.. seealso::
See reference documentation on how to use :ref:`primary variables <theming/module/variables>`, as
well as a list of all `primary variables
<{GITHUB_PATH}/addons/website/static/src/scss/primary_variables.scss>`_ available.
| Restart your script to immediately see the application of your changes.
| Don't forget to add the path to your manifest in the script and set your module as the app
to install.
To ensure your changes are applied correctly, log in to your website and check that your
color palette includes your specified colors.
.. tip::
You will need to override more variables to replicate the Airproof design. Remember to add them
throughout the creation of your website.
.. note::
The font families are from `Google fonts <https://fonts.google.com/>`_.
.. spoiler:: Solutions
To complete this exercise, you need to:
#. Create your :file:`primary_variables.scss` file. You can find all the necessary information in
the `primary_variables.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/primary_variables.scss>`_ file from our
example module.
#. Declare your file in the :file:`__manifest__.py` as indicated in the documentation.
#. Install your module via your script. In our example, it looks like this:
.. code-block:: xml
./odoo-bin --addons-path=../enterprise,addons,../myprojects --db-filter=theming -d theming
--without-demo=all -i website_airproof --dev=xml
.. _tutorials/website_theme/theming/bootstrap_variables:
Declare Bootstrap variables
===========================
On top of the default Odoo variables, you can also redefine the Bootstrap variables. Bootstrap is a
front-end framework which is included by default in Odoo.
Based on the Airproof design, define the following elements:
- Headings font sizes :
- h1 : 3.125rem
- h2 : 2.5rem
- h3 : 2rem
- h4 : 1.75rem
- h5 : 1.5rem
- h6 : 1.25rem
- Inputs border radius : 10px
- Inputs border color : black
- Inputs border width : 1px
- Large buttons border radius : 0px 10px 10px 10px
.. seealso::
- See reference documentation on how to use :ref:`theming/module/bootstrap`.
- A list of all `Bootstrap variables
<{GITHUB_PATH}/addons/web/static/lib/bootstrap/scss/_variables.scss>`_ used by Odoo.
- And `Bootstrap framework <https://getbootstrap.com/docs/4.6/getting-started/introduction/>`_
official documentation.
.. tip::
- You will need to override more variables to replicate the Airproof design. Remember to add them
throughout the creation of your website.
- Make it a habit to regularly check locally that your changes have been successfully applied
and have not caused any errors.
.. spoiler:: Solutions
To complete this exercise, you need to:
#. Create your :file:`bootstrap_overridden.scss` file. You can find all the necessary information
in the `bootstrap_overridden.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/bootstrap_overridden.scss>`_ file from
our example module.
#. Declare your file in the :file:`__manifest__.py` as indicated in the documentation.
.. _tutorials/website_theme/theming/presets:
Define presets
==============
In addition to the variables we have just covered, you can also activate specific views to modify
the design.
Add your :file:`presets.xml` file and based on the Airproof design, activate the appropriate views
to meet the following client requests:
- Deactivate the Call-to-action in the header.
- Deactivate the wishlist feature in the shop but activate it on the product page.
- On the shop page, activate the filtering by categories only on the left side.
.. seealso::
| See how you can define your :ref:`presets <theming/module/views/presets>`.
| To start writing your file, follow the instructions for any Odoo XML page described in
:doc:`/developer/howtos/website_themes/layout`.
.. tip::
- To complete the exercise, you need to install the **eCommerce** (`website_sale`) and
**wishlist** (`website_sale_whishlist`) applications. **Be careful!** Referencing an
application in your code that hasn't been installed will result in an error.
- | In order to find the templates to activate or not, go to the source code:
`odoo/addons/website/views/**`.
| For example, you can find all the templates for the header in
`website_templates.xml <{GITHUB_PATH}/addons/website/views/website_templates.xml>`_.
- To see the effect of your presets, add some **products** (*Airproof Mini*, *Airproof Robin*,
*Warranty*, *Charger cable*) and create **eCommerce categories** (*Warranties*, *Accessories*,
and *Drones* with *Camera drones* and *Waterproof drones*) in the database. You will find the
`product images here <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content>`_.
- You will need to activate more views to replicate the Airproof design. Remember to add them
throughout the creation of your website.
.. spoiler:: Solutions
To deactivate the Call-to-action:
#. The view you have to find is in :file:`odoo/addons/website/views/website_templates.xml l:2113`
#. Create your :file:`presets.xml` file with the right records
.. code-block:: xml
:caption: ``/website_airproof/data/presets.xml``
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Disable Call-to-action in header -->
<record id="website.header_call_to_action" model="ir.ui.view">
<field name="active" eval="False"/>
</record>
</odoo>
#. In the manifest, add the 2 apps and declare your file.
.. code-block:: python
:caption: ``/website_airproof/__manifest__.py``
'depends': ['website_sale', 'website_sale_wishlist'],
'data': [
# Options
'data/presets.xml',
]

View File

@@ -0,0 +1,172 @@
==============================
Chapter 2 - Build your website
==============================
.. _tutorials/website_theme/build_website/page:
Create a page
=============
Now that the theme has been set up, let's move on to creating the content.
First of all, start by creating your first theme page: the home page. For now, only indicate “Hello”
as content in the page.
.. tip::
You will need to deactivate the default homepage.
.. seealso::
See reference documentation on how to :ref:`desactivate a default page
<website_themes/pages/default>` and how to :ref:`start a new page
<website_themes/pages/theme_pages>`.
.. spoiler:: Solutions
.. code-block:: python
:caption: ``/website_airproof/__manifest__.py``
'data': [
# Pages
'data/pages/home.xml',
]
.. code-block:: xml
:caption: ``/website_airproof/data/pages/home.xml``
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<!-- Deactivate default homepage -->
<record id="website.homepage" model="ir.ui.view">
<field name="active" eval="False"/>
</record>
<!-- Home -->
<record id="page_home" model="website.page">
<field name="name">Home</field>
<field name="is_published" eval="True"/>
<field name="key">website_airproof.page_home</field>
<field name="url">/</field>
<field name="type">qweb</field>
<field name="arch" type="xml">
<t t-name="website_airproof.page_home">
<t t-call="website.layout">
<!-- Title -->
<t t-set="additional_title">One step beyond the horizon | Airproof</t>
<!-- Content -->
<div id="wrap" class="oe_structure">
<p>Hello</p>
</div>
</t>
</t>
</field>
</record>
</data>
</odoo>
.. _tutorials/website_theme/build_website/media:
Add a media
===========
If you want the client to be able to reuse certain pictures that you are going to add on the
website, they must be added to the image library.
To do the test, declare the drone image to add it to the library. You will find the `drone picture
here <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/drone-robin.png>`_.
.. seealso::
See reference documentation on how to :ref:`add a media <website_themes/media/images>`.
Go to the :guilabel:`Website Builder`, double-click on the :guilabel:`logo`, and you will see the
drone image in the library.
.. spoiler:: Solutions
To complete this exercise, you need to:
#. Put your PNG in the right image folder.
#. Create your :file:`images.xml` file. You can find all the necessary information
in the `images.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/images.xml>`_
file from our example module.
#. Declare your file in the :file:`__manifest__.py`.
.. _tutorials/website_theme/build_website/building_blocks:
Add building blocks
===================
Now, let's get into the real work. Start adding content to the pages.
In an Odoo website, we create the content of a page using building blocks. These can be compared to
snippets editable by the user in the Website Builder. The standard main container for any snippet
is a `section`.
Based on the Airproof design, add the following elements to the homepage :
- Create a section with the 3 boxes using the :guilabel:`Big boxes` building block.
- For this section, you don't want the future user to be able to edit it via the Website Builder.
- Put an opacity filter on the background image of the 3 boxes.
- Create another section containing the title and icons.
You can use these `images <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content>`_ and `icons
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/icons>`_.
.. seealso::
See reference documentation on how to :ref:`write standard snippets
<website_themes/building_blocks/layout>`.
.. image:: 02_build_website/building-blocks.png
:alt: Airproof building blocks.
:scale: 75%
.. tip::
To determine the code needed to create your building blocks :
- | Create a test page via the website builder.
| Drag & drop the building block that interests you and apply the right design.
| Use the code generated via :guilabel:`Editor HTML/SCSS` in the menu.
- You can also find the original building block code in Odoo :
:file:`odoo/addons/website/views/snippets/**.xml`.
.. spoiler:: Solutions
Find the solution in our Airproof example on `home.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/pages/home.xml>`_.
.. _tutorials/website_theme/build_website/navigation:
Navigation
==========
For now, the client is fine with the default header but has requested some navigation adjustments.
The client has requested the following changes:
- Remove the link to the homepage and the shop.
- Add a link to the future “About us” page.
- Replace the default blog item with a dropdown to display the different blogs: “Our latest news”
and “Tutorials”.
- Add a mega-menu “Waterproof drones” to display the different products.
.. seealso::
- You can find the original mega-menu templates code in Odoo :
`odoo/addons/website/views/snippets/s_mega_menu_**.xml
<{GITHUB_PATH}/addons/website/views/snippets>`_
- See reference documentation on how to modifiy the
:doc:`/developer/howtos/website_themes/navigation`.
.. image:: 02_build_website/mega-menu.png
:alt: Aiproof mega-menu.
.. tip::
- Make sure the Blog app is installed and create the two different blogs in the backend.
- Create the different products via the backend. You can use these `product pictures
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content>`_.
.. spoiler:: Solutions
Find the solution in our Airproof example on `menu.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/menu.xml>`_.

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@@ -0,0 +1,356 @@
=================================
Chapter 3 - Customisation, Part I
=================================
.. _tutorials/website_theme/customisation_part1/custom_scss:
Add custom SCSS
===============
You've adjusted Odoo and Bootstrap variables and set presets, yet you still notice disparities
between your website and the client's design. The only solution is to incorporate custom SCSS.
In :file:`theme.scss`, reproduce the following design elements:
- Add a **green underline** on active nav items.
- Modify the **arrow** for collapsible nav items.
- Modify the **slider's arrows** by adding a green background and changing their design.
You will find the various `media here
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/icons>`_.
.. seealso::
See reference documentation on how to :ref:`add your SCSS rules <theming/assets/styles>`.
.. image:: 03_customisation_part1/menu.png
:scale: 50%
.. image:: 03_customisation_part1/slider.png
.. note::
| It's always preferable to include all your SCSS rules in `#wrapwrap`. This ID is applied to the
div that groups the :guilabel:`header`, :guilabel:`footer`, and :guilabel:`main` content of all
your pages.
| So you will be sure that your rules will only have an impact on the website parts.
.. spoiler:: Solutions
Find the solution in our Airproof example on `header.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/layout/header.scss>`_
and `caroussel.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/snippets/caroussel.scss>`_.
.. _tutorials/website_theme/customisation_part1/custom_js:
Add custom JS
=============
Now, let's add a mouse follower to the website. This interactive element will enhance the browsing
experience, making it more engaging and visually appealing.
.. image:: 03_customisation_part1/mouse-follower.gif
Use your JavaScript skills to implement this.
.. seealso::
See reference documentation on how to :ref:`add Javascript code <theming/assets/interactivity>`.
.. spoiler:: Solutions
Find the solution in our Airproof example on `mouse_follower.js
<{GITHUB_TUTO_PATH}/website_airproof/static/src/js/mouse_follower.js>`_ and `mouse_follower.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/components/mouse_follower.scss>`_.
.. _tutorials/website_theme/customisation_part1/custom_header:
Create a custom header
======================
With variables, presets, and custom SCSS in place, it's time to refine the layout and add key
cross-page elements, starting with the header.
Based on the Airproof design, create a custom header with the following elements:
- A centered logo. Ensure to declare the logo so that it appears automatically in the header.
- A custom shopping cart icon.
- A login/user as a button.
- Navigation text to 14px.
You can find the `logo
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/branding/airproof-logo.svg>`_,
`cart icon <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/icons/shopping.svg>`_ and
`template illustration
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/wbuilder/template-header-opt.svg>`_.
.. seealso::
See reference documentation on how to:
- create :ref:`custom headers <website_themes/layout/header/custom>`,
- do a :ref:`website_themes/layout/xpath`,
- declare a :ref:`website_themes/media/images/use/logo`.
.. image:: 03_customisation_part1/header.png
.. tip::
- Base yourself on the code of existing header templates that you can find in
`odoo/addons/website/views/website_templates.xml
<{GITHUB_PATH}/addons/website/views/website_templates.xml>`_.
- A good practise should be to create different files to manage your custom views and templates.
For example, everything concerning the general layout (header, footer...) in
:file:`website_templates.xml`, everything related to blog in :file:`website_blog_templates.xml`,
to event in :file:`website_event_templates.xml`, etc.
- | To modify the cart icon, you can use an `XPath`.
| Since this is linked to eCommerce, place it in a new file called
:file:`website_sale_templates.xml`.
- Don't forget to continue making as many modifications as you can through the :file:`Bootstrap
variables` and :file:`primary variables` (font, colors, size...). You can use them to help you
with this exercise.
.. spoiler:: Solutions
Find the solution in our Airproof example for:
- the xml structure and to add the template to the options list on
`website_template.xml <{GITHUB_TUTO_PATH}/website_airproof/views/website_templates.xml>`_.
- disable the default header:
.. code-block:: xml
:caption: ``/website_airproof/data/presets.xml``
<!-- Disable default header -->
<record id="website.template_header_default" model="ir.ui.view">
<field name="active" eval="False"/>
</record>
- record the logo:
.. code-block:: xml
:caption: ``/website_airproof/data/images.xml``
<!-- Set as the logo of the website -->
<record id="website.default_website" model="website">
<field name="logo" type="base64" file="website_airproof/static/src/img/content/branding/airproof-logo.svg"/>
</record>
- declare your :file:`website_templates.xml` file along with all the new ones in your
:file:`manifest`.
- make the use of `primaries
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/primary_variables.scss>`_ like
`header-template`, `navbar-font`, `header-font-size`...
- use `bootstrap_overridden
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/bootstrap_overridden.scss>`_ like
`$navbar-light-color`, `$navbar-light-hover-color`, `$navbar-padding-y`...
- add some `scss <{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/layout/header.scss>`_
rules.
.. _tutorials/website_theme/customisation_part1/custom_footer:
Create a custom footer
======================
The client is delighted with the new header, as it aligns perfectly with the provided design. Now,
he wants a matching custom footer.
Based on the Airproof design, create a custom footer with the following elements:
- A section for newsletter subscription.
- A section for the copyright and social media.
You will find the `icons here <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/icons>`_.
.. seealso::
See reference documentation on how to create a :ref:`custom footer
<website_themes/layout/footer/custom>` and adapt the :ref:`website_themes/layout/copyright`.
.. image:: 03_customisation_part1/footer.png
.. tip::
- You can enable or disable the copyright section via the presets.
- For the newsletter section to work, you need to install the `website_mass_mailing` application.
.. spoiler:: Solutions
To complete this exercise, you need to:
- add `mass mailing` to your depends:
.. code-block:: python
:caption: ``/website_airproof/__manifest__.py``
'depends': ['website_sale', 'website_sale_wishlist', 'website_blog',
'website_mass_mailing'],
- find the xml structure and add the template to the options list on
`website_template.xml <{GITHUB_TUTO_PATH}/website_airproof/views/website_templates.xml>`_.
- disable the default footer and enable the copyright:
.. code-block:: xml
:caption: ``/website_airproof/data/presets.xml``
<!-- Disable Default Footer -->
<record id="website.footer_custom" model="ir.ui.view">
<field name="active" eval="False"/>
</record>
<!-- Enable Copyright -->
<record id="website.footer_no_copyright" model="ir.ui.view">
<field name="active" eval="False"/>
</record>
- make the use of `primaries
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/primary_variables.scss>`_ like
`footer-template`, `footer`, `o-cc4-link`...
- add a little scss rule for the `newsletter
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/snippets/newsletter.scss>`_ section.
.. _tutorials/website_theme/customisation_part1/custom_building_blocks:
Create your custom building blocks
==================================
To allow your client to further customize his website, create tailor-made building blocks that he
can freely drag & drop onto different pages.
Based on the Airproof design, create a custom carousel snippet to showcase drones. Then, add it as
cover section on your homepage.
#. Create the snippet template and add it to the list of building blocks available in the website
builder. Here you will find the `images
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/snippets/s_airproof_caroussel>`_ and
`snippet illustration
<{GITHUB_TUTO_PATH}/website_airproof/static/src/img/wbuilder/s-airproof-snippet.svg>`_.
.. seealso::
See reference documentation on how to create a :ref:`custom building blocks
<website_themes/building_blocks/custom>`.
.. image:: 03_customisation_part1/custom-building-block.png
#. Add an option in the Website Builder to allow users to choose between a blue or green bubble
shadow.
.. seealso::
See reference documentation on how to add :ref:`snippet options
<website_themes/building_blocks/custom/options>`.
.. image:: 03_customisation_part1/custom-building-block-option.png
:scale: 75%
#. Add the snippet on your homepage.
.. tip::
Don't forget to always properly declare your new files in your :file:`__manifest__.py` and follow
the good :ref:`folder structure <theming/module/structure>` seen previously.
.. spoiler:: Solutions
To complete this exercise, you need to:
#. Create your template.
- You can find all the necessary information in `s_airproof_carousel.xml
<{GITHUB_TUTO_PATH}/website_airproof/views/snippets/s_airproof_carousel.xml>`_ file and
`s_airproof_carousel/000.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/snippets/s_airproof_carousel/000.scss>`_
file from our example module.
- Record your images in `images.xml <{GITHUB_TUTO_PATH}/website_airproof/data/images.xml>`_.
- Declare your files in the `__manifest__.py
<{GITHUB_TUTO_PATH}/website_airproof/__manifest__.py>`_.
- Add it to the list of building blocks. In our example, it looks like this:
.. code-block:: xml
:caption: ``/website_airproof/views/snippets/options.xml``
<!-- Add custom snippets to the builder -->
<template id="snippets" inherit_id="website.snippets" name="Airproof - Custom Snippets">
<xpath expr="//*[@id='default_snippets']" position="before">
<t id="x_theme_snippets">
<div id="x_airproof_snippets" class="o_panel">
<div class="o_panel_header">Airproof</div>
<div class="o_panel_body">
<!-- Carousel snippet -->
<t t-snippet="website_airproof.s_airproof_carousel"
t-thumbnail="/website_airproof/static/src/img/wbuilder/s-airproof-snippet.svg">
<keywords>Carousel block</keywords>
</t>
</div>
</div>
</t>
</xpath>
</template>
#. Add the option to the Website Builder. In our example, it looks like this:
.. code-block:: xml
:caption: ``/website_airproof/views/snippets/s_airproof_carousel.xml``
<!-- Add options to snippets -->
<template id="snippet_options" inherit_id="website.snippet_options" name="Airproof -
Snippets Options">
<xpath expr="." position="inside">
<!-- *** Carousel snippet : blue or green bubble *** -->
<div data-selector=".x_bubble_item">
<we-button-group string="Bubble shadow">
<we-button data-select-class="x_bubble1">Blue</we-button>
<we-button data-select-class="x_bubble2">Green</we-button>
</we-button-group>
</div>
</xpath>
</template>
Additionally, the SCSS related to the bubbles in the `s_airproof_carousel/000.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/snippets/s_airproof_carousel/000.scss>`_ file.
#. Add your snippet to the homepage. You can find all the necessary information in the `home.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/pages/home.xml>`_ file from our example module.
.. _tutorials/website_theme/customisation_part1/custom_dynamic_template:
Create a new dynamic snippets template
======================================
| Dynamic snippets are useful building blocks. These allow you to fetch information from the backend
and display it on the website according to certain filters.
| There are already several layout templates for displaying dynamic snippets. However, none of the
existing templates fully match your client's needs.
Based on the Airproof design, create a custom template that you will apply to a product dynamic
snippet on the homepage.
#. First, create a custom template that will be added to the list of dynamic products templates. It
has to include the following elements:
- Add a :guilabel:`Discover more` link.
- Add a hover effect on cards.
- Move the navigation arrows.
You will find the `icons here <{GITHUB_TUTO_PATH}/website_airproof/static/src/img/content/icons>`_.
.. seealso::
See reference documentation on how to :ref:`create a template for dynamic snippets
<website_themes/building_blocks/custom/dynamic>`.
.. image:: 03_customisation_part1/custom-template.png
.. tip::
You can verify in the Website Builder that your template appears in the list of available
templates for the product dynamic snippet.
#. Then, add a product dynamic snippet with the template you just created to the homepage.
.. seealso::
See reference documentation on how to :ref:`call a template
<website_themes/building_blocks/custom/dynamic/call>`.
.. spoiler:: Solutions
To complete this exercise, you need to:
#. Create your snippet template. You can find all the necessary information in the
`options.xml <{GITHUB_TUTO_PATH}/website_airproof/views/snippets/options.xml>`_
file and `caroussel.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/snippets/caroussel.scss>`_ file from our
example module.
#. Apply the template to a product dynamic snippet on the homepage. You can find all the
necessary information in the `home.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/pages/home.xml>`_ file from our example module.

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -0,0 +1,192 @@
==================================
Chapter 4 - Customisation, Part II
==================================
.. _tutorials/website_theme/customisation_part2/background_shape:
Create a custom background shape
================================
Shapes are decorative elements that can be applied to backgrounds or images. They are SVG files
that can be animated and customized with different colors.
#. To better align with the website's desired atmosphere, create a custom background shape that the
client can reuse on different blocks.
Create your custom shape using the following setup:
- Declare your shape. You can find the original `SVG shape here
<{GITHUB_TUTO_PATH}/website_airproof/shape-waves.svg>`_.
- Set the base color of the shape to the theme's green, and add it to the list of available
shapes.
.. seealso::
See reference documentation on how to add a :ref:`custom background shapes
<website_themes/shapes/bg/custom>`.
.. image:: 04_customisation_part2/shape.png
.. tip::
| **Be careful,** there is a trick!
| In your shape SVG file, you have to use the colors from the default Odoo palette.
| Here, I want it to match my primary color 3 (`#CEF8A1`). Therefore, in the SVG file, you must
use color 3 from Odoo's default palette (`#F6F6F6`).
.. spoiler:: Solutions
Find the solution in our Airproof example for:
- the shape declaration on `shapes.xml <{GITHUB_TUTO_PATH}/website_airproof/data/shapes.xml>`_.
- adding the shape to the list thanks to
`primary_variable.scss
<{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/primary_variables.scss>`_ and `option.xml
<{GITHUB_TUTO_PATH}/website_airproof/views/snippets/options.xml>`_.
2. Based on the Airproof design, apply the shape you just added to a `Text-Image` building block on
the homepage:
- Ensure the shape is in the right position.
- Set its color to the theme's light blue.
.. seealso::
See reference documentation on how to use :ref:`background shapes
<website_themes/shapes/bg/custom/use>`.
.. image:: 04_customisation_part2/shape-section.png
.. tip::
Unlike a standard Odoo shapes, when applying a custom shape to a section, replace `web_editor`
with `illustration` in the shape class.
.. spoiler:: Solutions
.. code-block:: xml
:caption: ``/website_airproof/data/pages/home.xml``
<!-- Text-image block & Background shape -->
<section class="s_text_image o_cc o_cc5 o_colored_level pt120 pb96"
data-snippet="s_image_text" data-name="Image - Text" style="background-color: rgb(41, 128,
187);" data-oe-shape-data="{'shape': 'illustration/airproof/waves', 'colors': {'c3': '#BBE1FA'},
'flip': ['x']}">
<div class="o_we_shape o_illustration_airproof_waves o_we_flip_x" style="background-image:
url('/web_editor/shape/illustration%2Fairproof%2Fwaves.svg?c2=%23BBE1FA');
background-position: 100% 100%;"/>
[...]
</section>
.. _tutorials/website_theme/customisation_part2/background_gradient:
Add a background gradient
=========================
Apply a custom background gradient to your ”*Latest products*” block, transitioning from blue
`rgb(11, 142, 230)` to dark blue `rgb(41, 128, 187)`.
.. seealso::
See reference documentation on how to use :doc:`/developer/howtos/website_themes/gradients`.
.. spoiler:: Solutions
.. code-block:: xml
:caption: ``/website_airproof/data/pages/home.xml``
<!-- Latest products section -->
<section class="s_parallax o_colored_level o_cc o_cc5 s_parallax_no_overflow_hidden pt40 pb32"
data-scroll-background-ratio="0" data-snippet="s_parallax" data-name="Parallax"
style="background-image: linear-gradient(0deg, rgb(41, 128, 187) 0%, rgb(11, 142, 230) 100%)
!important;">
[...]
</section>
.. _tutorials/website_theme/customisation_part2/animations:
Animations
==========
The client loves the overall design but finds the page a bit static. Enhance page interactivity with
animations such as `fade-in`, `rotate`, `bounce`, etc. These can be applied to columns, images,
texts, buttons…
Based on the airproof design, animate the following elements:
- the text of the first slide of the carousel.
- the sticker and the photo of the drone from the first slide.
- the 4 columns with icons.
Adjust animation delays for smoother transitions.
.. seealso::
See reference documentation on how to apply :doc:`/developer/howtos/website_themes/animations`.
.. image:: 04_customisation_part2/animations.gif
.. spoiler:: Solutions
Find the solution in our Airproof example on `home.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/pages/home.xml>`_.
.. code-block:: xml
:caption: Image animation
<img src="/web/image/website_airproof.img_sticker" class="img img-fluid position-absolute
x_sticker o_animate o_anim_rotate_in o_visible" style="animation-delay: 0.8s;
--wanim-intensity: 30;"/>
<img src="/web/image/website_airproof.img_drone" class="img img-fluid o_animate
o_anim_zoom_out o_visible" alt="Drone"/>
.. code-block:: xml
:caption: Text animation
<span class="o_animated_text o_animate o_anim_fade_in o_anim_from_bottom o_visible">One
step</span>
.. code-block:: xml
:caption: Columns animation
<div class="o_grid_item o_colored_level g-height-7 g-col-lg-3 col-lg-3 text-center
o_anim_fade_in o_animate o_anim_from_bottom o_visible" style="z-index: 2;
grid-area: 6 / 1 / 12 / 4; --wanim-intensity: 15;">
</div>
.. _tutorials/website_theme/customisation_part2/forms:
Forms
=====
The forms in Odoo are very powerful. They can send emails directly to a personal inbox or integrate
directly with other Odoo applications. This is great, as one of your client's main priorities is
after-sales service. Therefore, the contact form must be properly configured.
Based on the airproof design, create a contact page. Remember to disable the default one and add the
new page link to the menu. The client has the following requests for their contact form:
- *Name* and *email address* field.
- *Company name* field.
- *Conditional VAT* field displayed only if *Company name* is filled in.
- All fields should be mandatory, except for *Company name*.
- Form submission must trigger an email.
- After form submission, the `thank-you message` should remain visible on the contact page.
.. seealso::
See reference documentation on how to:
- :ref:`deactivate default pages <website_themes/pages/default>`,
- :ref:`create a new page <website_themes/pages/theme_pages>`,
- :ref:`add a menu item <website_themes/navigation/menu>`,
- :doc:`create a form </developer/howtos/website_themes/forms>`.
.. tip::
To determine the correct code for your form:
- | Create a test page via the Website Builder.
| Drag & drop the building block that interests you and apply the right design.
| Use the code generated through :guilabel:`Editor HTML/SCSS`.
- You can also find the original building block code in Odoo:
`odoo/addons/website/views/snippets/s_website_form.xml
<{GITHUB_PATH}/addons/website/views/snippets/s_website_form.xml>`_.
.. spoiler:: Solutions
Find the solution in our Airproof example on `contact.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/pages/contact.xml>`_.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -0,0 +1,86 @@
=============================
Chapter 5 - Dynamic templates
=============================
.. _tutorials/website_theme/dynamic_templates/shop:
Adapt the shop template
=======================
Now, let's adapt the dynamic sections of the website. As you may know, some pages such as those for
eCommerce are automatically generated. Pages like the shop, product, and checkout are automatically
generated when the `website_sale` application is installed. These template pages pull their
displayed information from the backend.
To modify these pages, we need to edit the standard Odoo template. This can be done using SCSS,
presets, and especially XPath. Locate the standard Odoo template you want to modify and extend it
using `XPath`. Following the Airproof design, let's begin by modifying the shop view.
#. First, locate the standard template in Odoo : :menuselection:`website_sale --> templates.xml -->
id="products"`.
#. Apply all changes in your :file:`website_sale_templates.xml` file. Start by:
- Add a banner.
- Adapt the layout of the e-commerce category filtering on the left.
- Remove the search bar (you can remove it from both the shop and the product pages at the same
time).
- Move the breadcrumb.
- Hide the list or grid view option.
- Create the appropriate design and information for the product cards.
.. image:: 05_dynamic_templates/airproof-shop-page.png
:align: center
.. tip::
- Apply your modifications using presets, XPath and SCSS.
- To enable attribute/variant filtering, activate the
:doc:`/applications/sales/sales/products_prices/products/variants` option in the
website backend settings and :ref:`configure attributes and variants
<ecommerce/products/product-variants>` for the products.
.. spoiler:: Solutions
Find the solution in our Airproof example on `presets.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/presets.xml>`_, `website_sale_templates.xml
<{GITHUB_TUTO_PATH}/website_airproof/views/website_sale_templates.xml>`_ part *shop page*, and
`shop.scss <{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/pages/shop.scss>`_.
.. _tutorials/website_theme/dynamic_templates/product:
Adapt the product page template
===============================
The client is thrilled with the shop modifications. Next, let's apply our design to the product
pages. Based on the Airproof design below, adapt a few elements including:
- Remove the search bar (if not done with the previous exercise).
- Remove the quantity selector, Terms and Conditions, and share icons.
- Update the :guilabel:`Add to cart` button icon.
- Insert a title above the product specifications (this section appears only when the product
has one variant per attribute).
- Design the appropriate layout for the carousel.
- Add a title and apply the previously created product template to the `Alternative products`
section (ensure alternative products are assigned on the product in the backend for this section
to appear).
- Implement a new drop zone below product details, visible on all products. As a use case, add an
`Text-Image` building block using the Website Builder (e.g.: See Airproof product page screenshot
with “*Six reasons to buy…*”).
.. seealso::
See reference documentation on how to create a :ref:`website_themes/layout/dropzone`.
.. image:: 05_dynamic_templates/airproof-product-page.png
:align: center
.. tip::
- Make your modifications using presets, XPath, and SCSS. Be sure to comment your code properly
so you can find your way around.
- The drop zone will be visible on all products. To create a specific dropzone per product, you
need to add a new field to the product model.
.. spoiler:: Solutions
Find the solution in our Airproof example on `presets.xml
<{GITHUB_TUTO_PATH}/website_airproof/data/presets.xml>`_, `website_sale_templates.xml
<{GITHUB_TUTO_PATH}/website_airproof/views/website_sale_templates.xml>`_ part *product page*, and
`product_page.scss <{GITHUB_TUTO_PATH}/website_airproof/static/src/scss/pages/product_page.scss>`_.

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@@ -0,0 +1,84 @@
======================
Chapter 6 - Going live
======================
.. _tutorials/website_theme/going_live/translations:
Translations
============
Congratulations! Your client has a beautifully designed homepage and contact page, and the eCommerce
is fully adapted to the Airproof design. Amazing!
Now, the client wants the website translated into French. To do so:
#. Add French to the website in the settings and enable the language switcher in the header via
presets.
#. Then for the translation itself, you have two options. We shall therefore test both:
- Translate the content of the homepage carousel through the backend.
- But for the menu, make the translations through the frontend.
#. Export the French :file:`.po` file for your Airproof module and place it in the :file:`/i18n`
translations folder.
#. If you would like, you can add more translations directly by editing the :file:`.po`
file. (Using Poedit software, your code editor, or another translation tool.)
.. seealso::
See reference documentation on :ref:`website_themes/translations/backend` and
:ref:`website_themes/translations/frontend` translations, and how to
:ref:`website_themes/translations/export` them.
.. note::
- Be careful when using Poedit, as it doesn't handle tags with styles well and generates an
:file:`.mo` file.
- To see the changes made directly via the :file:`.po` file, you will need to manually import the
file.
.. spoiler:: Solutions
Take a look at what the file `i18n/fr_BE.po <{GITHUB_TUTO_PATH}/website_airproof/i18n/fr_BE.po>`_
of our Airproof example looks like.
.. _tutorials/website_theme/going_live/module_import:
Module import
=============
Great job! The website is now completely finished and your module is ready for installation in the
client's SaaS database.
Just before that, test the import process on a new database.
.. seealso::
See reference documentation on how to :doc:`deploy a module
</developer/howtos/website_themes/going_live>` on an Odoo SaaS database.
.. tip::
- Ensure the `base_import_module` is installed on the database before the module installation.
- Verify all required applications are installed.
- Skip the theme installation steps and start from scratch.
- Manually import translations after module installation, as they won't apply automatically.
Conclusion
==========
Congratulations on completing the **Build a module for a website theme** tutorial!
You've successfully navigated through every stage, from setting up your development environment to
launching a fully customized Odoo website theme.
Throughout this journey, you've mastered:
|**Theme module creation** - setting up the structure, declaring Odoo and Bootstrap variables.
|**Website building** - creating pages, adding media, and constructing dynamic building blocks.
|**Advanced customization** - implementing custom SCSS, JavaScript, headers, footers, and unique
design elements.
|**Visual enhancements** - designing background shapes, gradients, and animations for an
engaging user experience.
|**eCommerce optimization** - adapting shop and product templates for a seamless shopping
experience.
|**Final preparations** - managing translations and ensuring a smooth module import.
| With these skills, you're now ready to design and develop professional, fully customized website
themes. Well done!
| We can't wait to see the amazing themes you'll create in the future.

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB